@ivotoby/openapi-mcp-server 1.12.5 → 1.14.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/dist/cli.js CHANGED
@@ -11659,6 +11659,8 @@ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"
11659
11659
 
11660
11660
  // src/server.ts
11661
11661
  import { Server } from "@modelcontextprotocol/sdk/server/index.js";
11662
+ import { readFileSync } from "node:fs";
11663
+ import { Agent as HttpsAgent } from "node:https";
11662
11664
  import {
11663
11665
  ListToolsRequestSchema,
11664
11666
  CallToolRequestSchema,
@@ -14406,14 +14408,39 @@ function generateToolId(method, path2) {
14406
14408
  return `${method.toUpperCase()}::${sanitizedPath}`;
14407
14409
  }
14408
14410
 
14411
+ // src/utils/logger.ts
14412
+ var Logger = class {
14413
+ constructor(verbose = true) {
14414
+ this.verbose = verbose;
14415
+ }
14416
+ setVerbose(verbose) {
14417
+ this.verbose = verbose ?? true;
14418
+ }
14419
+ warn(message, ...optionalParams) {
14420
+ if (this.verbose) {
14421
+ console.warn(message, ...optionalParams);
14422
+ }
14423
+ }
14424
+ error(message, ...optionalParams) {
14425
+ if (this.verbose) {
14426
+ console.error(message, ...optionalParams);
14427
+ }
14428
+ }
14429
+ fatal(message, ...optionalParams) {
14430
+ console.error(message, ...optionalParams);
14431
+ }
14432
+ };
14433
+
14409
14434
  // src/openapi-loader.ts
14410
14435
  var OpenAPISpecLoader = class {
14411
14436
  /**
14412
14437
  * Disable name optimization
14413
14438
  */
14414
14439
  disableAbbreviation;
14440
+ logger;
14415
14441
  constructor(config) {
14416
14442
  this.disableAbbreviation = config?.disableAbbreviation ?? false;
14443
+ this.logger = new Logger(config?.verbose ?? true);
14417
14444
  }
14418
14445
  /**
14419
14446
  * Load an OpenAPI specification from various sources
@@ -14633,7 +14660,7 @@ var OpenAPISpecLoader = class {
14633
14660
  */
14634
14661
  determineParameterType(paramSchema, paramName) {
14635
14662
  if (Object.keys(paramSchema).length === 0 && typeof paramSchema !== "boolean") {
14636
- console.warn(
14663
+ this.logger.warn(
14637
14664
  `Parameter '${paramName}' schema was empty after inlining (potential cycle or unresolvable ref), defaulting to string.`
14638
14665
  );
14639
14666
  return "string";
@@ -14689,19 +14716,19 @@ var OpenAPISpecLoader = class {
14689
14716
  if (resolvedParam && "name" in resolvedParam && "in" in resolvedParam) {
14690
14717
  paramObj = resolvedParam;
14691
14718
  } else {
14692
- console.warn(
14719
+ this.logger.warn(
14693
14720
  `Could not resolve path-level parameter reference or invalid structure: ${param.$ref}`
14694
14721
  );
14695
14722
  continue;
14696
14723
  }
14697
14724
  } else {
14698
- console.warn(`Could not parse path-level parameter reference: ${param.$ref}`);
14725
+ this.logger.warn(`Could not parse path-level parameter reference: ${param.$ref}`);
14699
14726
  continue;
14700
14727
  }
14701
14728
  } else if ("name" in param && "in" in param) {
14702
14729
  paramObj = param;
14703
14730
  } else {
14704
- console.warn(
14731
+ this.logger.warn(
14705
14732
  "Skipping path-level parameter due to missing 'name' or 'in' properties and not being a valid $ref:",
14706
14733
  param
14707
14734
  );
@@ -14717,7 +14744,7 @@ var OpenAPISpecLoader = class {
14717
14744
  if (!["get", "post", "put", "patch", "delete", "options", "head"].includes(
14718
14745
  method.toLowerCase()
14719
14746
  )) {
14720
- console.warn(`Skipping non-HTTP method "${method}" for path ${path2}`);
14747
+ this.logger.warn(`Skipping non-HTTP method "${method}" for path ${path2}`);
14721
14748
  continue;
14722
14749
  }
14723
14750
  const op = operation;
@@ -14755,19 +14782,19 @@ var OpenAPISpecLoader = class {
14755
14782
  if (resolvedParam && "name" in resolvedParam && "in" in resolvedParam) {
14756
14783
  paramObj = resolvedParam;
14757
14784
  } else {
14758
- console.warn(
14785
+ this.logger.warn(
14759
14786
  `Could not resolve parameter reference or invalid structure: ${param.$ref}`
14760
14787
  );
14761
14788
  continue;
14762
14789
  }
14763
14790
  } else {
14764
- console.warn(`Could not parse parameter reference: ${param.$ref}`);
14791
+ this.logger.warn(`Could not parse parameter reference: ${param.$ref}`);
14765
14792
  continue;
14766
14793
  }
14767
14794
  } else if ("name" in param && "in" in param) {
14768
14795
  paramObj = param;
14769
14796
  } else {
14770
- console.warn(
14797
+ this.logger.warn(
14771
14798
  "Skipping parameter due to missing 'name' or 'in' properties and not being a valid $ref:",
14772
14799
  param
14773
14800
  );
@@ -14818,19 +14845,19 @@ var OpenAPISpecLoader = class {
14818
14845
  if (resolvedRequestBody && "content" in resolvedRequestBody) {
14819
14846
  requestBodyObj = resolvedRequestBody;
14820
14847
  } else {
14821
- console.warn(
14848
+ this.logger.warn(
14822
14849
  `Could not resolve requestBody reference or invalid structure: ${op.requestBody.$ref}`
14823
14850
  );
14824
14851
  continue;
14825
14852
  }
14826
14853
  } else {
14827
- console.warn(`Could not parse requestBody reference: ${op.requestBody.$ref}`);
14854
+ this.logger.warn(`Could not parse requestBody reference: ${op.requestBody.$ref}`);
14828
14855
  continue;
14829
14856
  }
14830
14857
  } else if ("content" in op.requestBody) {
14831
14858
  requestBodyObj = op.requestBody;
14832
14859
  } else {
14833
- console.warn("Skipping requestBody due to invalid structure:", op.requestBody);
14860
+ this.logger.warn("Skipping requestBody due to invalid structure:", op.requestBody);
14834
14861
  continue;
14835
14862
  }
14836
14863
  let mediaTypeObj;
@@ -15033,12 +15060,15 @@ var ToolsManager = class {
15033
15060
  this.config = config;
15034
15061
  this.config.toolsMode = this.config.toolsMode || "all";
15035
15062
  this.specLoader = new OpenAPISpecLoader({
15036
- disableAbbreviation: this.config.disableAbbreviation
15063
+ disableAbbreviation: this.config.disableAbbreviation,
15064
+ verbose: this.config.verbose
15037
15065
  });
15066
+ this.logger = new Logger(this.config.verbose);
15038
15067
  }
15039
15068
  tools = /* @__PURE__ */ new Map();
15040
15069
  specLoader;
15041
15070
  loadedSpec;
15071
+ logger;
15042
15072
  /**
15043
15073
  * Get the OpenAPI spec loader instance
15044
15074
  */
@@ -15124,7 +15154,7 @@ var ToolsManager = class {
15124
15154
  }
15125
15155
  this.tools = filtered2;
15126
15156
  for (const [toolId, tool] of this.tools.entries()) {
15127
- console.error(`Registered tool: ${toolId} (${tool.name})`);
15157
+ this.logger.error(`Registered tool: ${toolId} (${tool.name})`);
15128
15158
  }
15129
15159
  return;
15130
15160
  }
@@ -15170,7 +15200,7 @@ var ToolsManager = class {
15170
15200
  }
15171
15201
  this.tools = filtered;
15172
15202
  for (const [toolId, tool] of this.tools.entries()) {
15173
- console.error(`Registered tool: ${toolId} (${tool.name})`);
15203
+ this.logger.error(`Registered tool: ${toolId} (${tool.name})`);
15174
15204
  }
15175
15205
  }
15176
15206
  /**
@@ -19061,8 +19091,9 @@ var ApiClient = class {
19061
19091
  * @param baseUrl - Base URL for the API
19062
19092
  * @param authProviderOrHeaders - AuthProvider instance or static headers for backward compatibility
19063
19093
  * @param specLoader - Optional OpenAPI spec loader for dynamic meta-tools
19094
+ * @param options - Optional HTTP client configuration
19064
19095
  */
19065
- constructor(baseUrl, authProviderOrHeaders, specLoader) {
19096
+ constructor(baseUrl, authProviderOrHeaders, specLoader, options) {
19066
19097
  this.axiosInstance = axios_default.create({
19067
19098
  baseURL: baseUrl.endsWith("/") ? baseUrl : `${baseUrl}/`,
19068
19099
  timeout: 3e4,
@@ -19071,8 +19102,9 @@ var ApiClient = class {
19071
19102
  // 50MB response body limit
19072
19103
  maxBodyLength: 50 * 1024 * 1024,
19073
19104
  // 50MB request body limit
19074
- maxRedirects: 5
19105
+ maxRedirects: 5,
19075
19106
  // Limit redirect chains to prevent abuse
19107
+ httpsAgent: options?.httpsAgent
19076
19108
  });
19077
19109
  if (!authProviderOrHeaders) {
19078
19110
  this.authProvider = new StaticAuthProvider();
@@ -19767,8 +19799,10 @@ var OpenAPIServer = class {
19767
19799
  promptsManager;
19768
19800
  resourcesManager;
19769
19801
  config;
19802
+ logger;
19770
19803
  constructor(config) {
19771
19804
  this.config = config;
19805
+ this.logger = new Logger(config.verbose);
19772
19806
  if (config.prompts?.length) {
19773
19807
  this.promptsManager = new PromptsManager({ prompts: config.prompts });
19774
19808
  }
@@ -19787,19 +19821,60 @@ var OpenAPIServer = class {
19787
19821
  if (this.resourcesManager) {
19788
19822
  capabilities.resources = {};
19789
19823
  }
19790
- this.server = new Server(
19791
- { name: config.name, version: config.version },
19792
- { capabilities }
19793
- );
19824
+ this.server = new Server({ name: config.name, version: config.version }, { capabilities });
19794
19825
  this.toolsManager = new ToolsManager(config);
19795
19826
  const authProviderOrHeaders = config.authProvider || new StaticAuthProvider(config.headers);
19796
- this.apiClient = new ApiClient(
19827
+ const apiClientOptions = this.createApiClientOptions();
19828
+ this.apiClient = apiClientOptions ? new ApiClient(
19797
19829
  config.apiBaseUrl,
19798
19830
  authProviderOrHeaders,
19799
- this.toolsManager.getSpecLoader()
19800
- );
19831
+ this.toolsManager.getSpecLoader(),
19832
+ apiClientOptions
19833
+ ) : new ApiClient(config.apiBaseUrl, authProviderOrHeaders, this.toolsManager.getSpecLoader());
19801
19834
  this.initializeHandlers();
19802
19835
  }
19836
+ createApiClientOptions() {
19837
+ const hasClientCert = !!this.config.clientCertPath;
19838
+ const hasClientKey = !!this.config.clientKeyPath;
19839
+ if (hasClientCert !== hasClientKey) {
19840
+ throw new Error("clientCertPath and clientKeyPath must be provided together");
19841
+ }
19842
+ if (this.config.clientKeyPassphrase && !hasClientKey) {
19843
+ throw new Error("clientKeyPassphrase requires clientKeyPath and clientCertPath");
19844
+ }
19845
+ const rejectUnauthorized = this.config.rejectUnauthorized ?? true;
19846
+ const shouldConfigureHttpsAgent = hasClientCert || hasClientKey || !!this.config.caCertPath || rejectUnauthorized === false;
19847
+ if (!shouldConfigureHttpsAgent) {
19848
+ return void 0;
19849
+ }
19850
+ let apiUrl;
19851
+ try {
19852
+ apiUrl = new URL(this.config.apiBaseUrl.trim());
19853
+ } catch {
19854
+ throw new Error("TLS options require apiBaseUrl to be a valid https:// URL");
19855
+ }
19856
+ if (apiUrl.protocol !== "https:") {
19857
+ throw new Error("TLS options require apiBaseUrl to use https://");
19858
+ }
19859
+ const httpsAgentOptions = {
19860
+ rejectUnauthorized
19861
+ };
19862
+ if (this.config.clientCertPath) {
19863
+ httpsAgentOptions.cert = readFileSync(this.config.clientCertPath, "utf8");
19864
+ }
19865
+ if (this.config.clientKeyPath) {
19866
+ httpsAgentOptions.key = readFileSync(this.config.clientKeyPath, "utf8");
19867
+ }
19868
+ if (this.config.caCertPath) {
19869
+ httpsAgentOptions.ca = readFileSync(this.config.caCertPath, "utf8");
19870
+ }
19871
+ if (this.config.clientKeyPassphrase) {
19872
+ httpsAgentOptions.passphrase = this.config.clientKeyPassphrase;
19873
+ }
19874
+ return {
19875
+ httpsAgent: new HttpsAgent(httpsAgentOptions)
19876
+ };
19877
+ }
19803
19878
  /**
19804
19879
  * Initialize request handlers
19805
19880
  */
@@ -19811,21 +19886,21 @@ var OpenAPIServer = class {
19811
19886
  });
19812
19887
  this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
19813
19888
  const { id, name, arguments: params } = request.params;
19814
- console.error("Received request:", request.params);
19815
- console.error("Using parameters from arguments:", params);
19889
+ this.logger.error("Received request:", request.params);
19890
+ this.logger.error("Using parameters from arguments:", params);
19816
19891
  const idOrName = typeof id === "string" ? id : typeof name === "string" ? name : "";
19817
19892
  if (!idOrName) {
19818
19893
  throw new Error("Tool ID or name is required");
19819
19894
  }
19820
19895
  const toolInfo = this.toolsManager.findTool(idOrName);
19821
19896
  if (!toolInfo) {
19822
- console.error(
19897
+ this.logger.error(
19823
19898
  `Available tools: ${Array.from(this.toolsManager.getAllTools()).map((t) => t.name).join(", ")}`
19824
19899
  );
19825
19900
  throw new Error(`Tool not found: ${idOrName}`);
19826
19901
  }
19827
19902
  const { toolId, tool } = toolInfo;
19828
- console.error(`Executing tool: ${toolId} (${tool.name})`);
19903
+ this.logger.error(`Executing tool: ${toolId} (${tool.name})`);
19829
19904
  try {
19830
19905
  const result = await this.apiClient.executeApiCall(toolId, params || {});
19831
19906
  return {
@@ -19856,10 +19931,7 @@ var OpenAPIServer = class {
19856
19931
  prompts: this.promptsManager.getAllPrompts()
19857
19932
  }));
19858
19933
  this.server.setRequestHandler(GetPromptRequestSchema, async (request) => {
19859
- return this.promptsManager.getPrompt(
19860
- request.params.name,
19861
- request.params.arguments
19862
- );
19934
+ return this.promptsManager.getPrompt(request.params.name, request.params.arguments);
19863
19935
  });
19864
19936
  }
19865
19937
  if (this.resourcesManager) {
@@ -20211,7 +20283,7 @@ function sync_default(start, callback) {
20211
20283
 
20212
20284
  // node_modules/yargs/lib/platform-shims/esm.mjs
20213
20285
  import { inspect } from "util";
20214
- import { readFileSync as readFileSync3 } from "fs";
20286
+ import { readFileSync as readFileSync4 } from "fs";
20215
20287
  import { fileURLToPath } from "url";
20216
20288
 
20217
20289
  // node_modules/yargs-parser/build/lib/index.js
@@ -21154,7 +21226,7 @@ function stripQuotes(val) {
21154
21226
  }
21155
21227
 
21156
21228
  // node_modules/yargs-parser/build/lib/index.js
21157
- import { readFileSync } from "fs";
21229
+ import { readFileSync as readFileSync2 } from "fs";
21158
21230
  var _a;
21159
21231
  var _b;
21160
21232
  var _c;
@@ -21181,7 +21253,7 @@ var parser = new YargsParser({
21181
21253
  if (typeof __require !== "undefined") {
21182
21254
  return __require(path2);
21183
21255
  } else if (path2.match(/\.json$/)) {
21184
- return JSON.parse(readFileSync(path2, "utf8"));
21256
+ return JSON.parse(readFileSync2(path2, "utf8"));
21185
21257
  } else {
21186
21258
  throw Error("only .json config files are supported in ESM");
21187
21259
  }
@@ -21233,12 +21305,12 @@ var YError = class _YError extends Error {
21233
21305
  };
21234
21306
 
21235
21307
  // node_modules/y18n/build/lib/platform-shims/node.js
21236
- import { readFileSync as readFileSync2, statSync as statSync2, writeFile } from "fs";
21308
+ import { readFileSync as readFileSync3, statSync as statSync2, writeFile } from "fs";
21237
21309
  import { format as format2 } from "util";
21238
21310
  import { resolve as resolve3 } from "path";
21239
21311
  var node_default2 = {
21240
21312
  fs: {
21241
- readFileSync: readFileSync2,
21313
+ readFileSync: readFileSync3,
21242
21314
  writeFile
21243
21315
  },
21244
21316
  format: format2,
@@ -21462,7 +21534,7 @@ var esm_default = {
21462
21534
  nextTick: process.nextTick,
21463
21535
  stdColumns: typeof process.stdout.columns !== "undefined" ? process.stdout.columns : null
21464
21536
  },
21465
- readFileSync: readFileSync3,
21537
+ readFileSync: readFileSync4,
21466
21538
  require: () => {
21467
21539
  throw new YError(REQUIRE_ERROR);
21468
21540
  },
@@ -24765,6 +24837,25 @@ function parseHeaders(headerStr) {
24765
24837
  }
24766
24838
  return headers;
24767
24839
  }
24840
+ function parseOptionalBoolean(value, optionName) {
24841
+ if (value === void 0 || value === null || value === "") {
24842
+ return void 0;
24843
+ }
24844
+ if (typeof value === "boolean") {
24845
+ return value;
24846
+ }
24847
+ if (typeof value !== "string") {
24848
+ throw new Error(`${optionName} must be a boolean value`);
24849
+ }
24850
+ const normalized = value.trim().toLowerCase();
24851
+ if (["true", "1", "yes", "on"].includes(normalized)) {
24852
+ return true;
24853
+ }
24854
+ if (["false", "0", "no", "off"].includes(normalized)) {
24855
+ return false;
24856
+ }
24857
+ throw new Error(`${optionName} must be one of: true, false, 1, 0, yes, no, on, off`);
24858
+ }
24768
24859
  function loadConfig() {
24769
24860
  const argv = yargs_default(hideBin(process.argv)).option("transport", {
24770
24861
  alias: "t",
@@ -24799,6 +24890,21 @@ function loadConfig() {
24799
24890
  alias: "H",
24800
24891
  type: "string",
24801
24892
  description: "API headers in format 'key1:value1,key2:value2'"
24893
+ }).option("client-cert", {
24894
+ type: "string",
24895
+ description: "Path to client certificate PEM file for mutual TLS"
24896
+ }).option("client-key", {
24897
+ type: "string",
24898
+ description: "Path to client private key PEM file for mutual TLS"
24899
+ }).option("ca-cert", {
24900
+ type: "string",
24901
+ description: "Path to custom CA certificate PEM file"
24902
+ }).option("client-key-passphrase", {
24903
+ type: "string",
24904
+ description: "Passphrase for encrypted client private key"
24905
+ }).option("reject-unauthorized", {
24906
+ type: "string",
24907
+ description: "Whether to reject untrusted server certificates"
24802
24908
  }).option("name", {
24803
24909
  alias: "n",
24804
24910
  type: "string",
@@ -24842,6 +24948,9 @@ function loadConfig() {
24842
24948
  }).option("resources-inline", {
24843
24949
  type: "string",
24844
24950
  description: "Provide resources directly as JSON string"
24951
+ }).option("verbose", {
24952
+ type: "string",
24953
+ description: "Enable verbose logging"
24845
24954
  }).help().parseSync();
24846
24955
  let transportType;
24847
24956
  if (argv.transport === "http" || process.env.TRANSPORT_TYPE === "http") {
@@ -24893,15 +25002,18 @@ function loadConfig() {
24893
25002
  if (normalized === "all" || normalized === "dynamic" || normalized === "explicit") {
24894
25003
  toolsMode = normalized;
24895
25004
  } else {
24896
- throw new Error(
24897
- "Invalid tools mode. Expected one of: all, dynamic, explicit"
24898
- );
25005
+ throw new Error("Invalid tools mode. Expected one of: all, dynamic, explicit");
24899
25006
  }
24900
25007
  }
24901
25008
  if (!apiBaseUrl) {
24902
25009
  throw new Error("API base URL is required (--api-base-url or API_BASE_URL)");
24903
25010
  }
24904
25011
  const headers = parseHeaders(argv.headers || process.env.API_HEADERS);
25012
+ const rejectUnauthorizedInput = parseOptionalBoolean(
25013
+ argv["reject-unauthorized"] ?? process.env.REJECT_UNAUTHORIZED,
25014
+ "--reject-unauthorized/REJECT_UNAUTHORIZED"
25015
+ );
25016
+ const verbose = parseOptionalBoolean(argv.verbose ?? process.env.VERBOSE, "--verbose/VERBOSE") ?? true;
24905
25017
  return {
24906
25018
  name: argv.name || process.env.SERVER_NAME || "mcp-openapi-server",
24907
25019
  version: argv["server-version"] || process.env.SERVER_VERSION || "1.0.0",
@@ -24910,6 +25022,11 @@ function loadConfig() {
24910
25022
  specInputMethod,
24911
25023
  inlineSpecContent,
24912
25024
  headers,
25025
+ clientCertPath: argv["client-cert"] || process.env.CLIENT_CERT_PATH,
25026
+ clientKeyPath: argv["client-key"] || process.env.CLIENT_KEY_PATH,
25027
+ caCertPath: argv["ca-cert"] || process.env.CA_CERT_PATH,
25028
+ clientKeyPassphrase: argv["client-key-passphrase"] || process.env.CLIENT_KEY_PASSPHRASE,
25029
+ rejectUnauthorized: rejectUnauthorizedInput ?? true,
24913
25030
  transportType,
24914
25031
  httpPort,
24915
25032
  httpHost,
@@ -24923,7 +25040,8 @@ function loadConfig() {
24923
25040
  promptsPath: argv.prompts || process.env.PROMPTS_PATH,
24924
25041
  promptsInline: argv["prompts-inline"] || process.env.PROMPTS_INLINE,
24925
25042
  resourcesPath: argv.resources || process.env.RESOURCES_PATH,
24926
- resourcesInline: argv["resources-inline"] || process.env.RESOURCES_INLINE
25043
+ resourcesInline: argv["resources-inline"] || process.env.RESOURCES_INLINE,
25044
+ verbose
24927
25045
  };
24928
25046
  }
24929
25047
 
@@ -24936,7 +25054,6 @@ import {
24936
25054
  import * as http3 from "http";
24937
25055
  import { randomUUID } from "crypto";
24938
25056
  var StreamableHttpServerTransport = class {
24939
- // Track if using an external server
24940
25057
  /**
24941
25058
  * Initialize a new StreamableHttpServerTransport
24942
25059
  *
@@ -24951,11 +25068,12 @@ var StreamableHttpServerTransport = class {
24951
25068
  * further handlers from running for those requests. The MCP handler should be added after
24952
25069
  * custom handlers and will return early for non-MCP paths.
24953
25070
  */
24954
- constructor(port, host = "127.0.0.1", endpointPath = "/mcp", server) {
25071
+ constructor(port, host = "127.0.0.1", endpointPath = "/mcp", server, verbose = true) {
24955
25072
  this.port = port;
24956
25073
  this.host = host;
24957
25074
  this.endpointPath = endpointPath;
24958
25075
  this.isExternalServer = !!server;
25076
+ this.logger = new Logger(verbose);
24959
25077
  if (server) {
24960
25078
  this.server = server;
24961
25079
  this.server.on("request", this.handleRequest.bind(this));
@@ -24973,6 +25091,8 @@ var StreamableHttpServerTransport = class {
24973
25091
  // Maps request IDs to session IDs
24974
25092
  healthCheckPath = "/health";
24975
25093
  isExternalServer;
25094
+ // Track if using an external server
25095
+ logger;
24976
25096
  /**
24977
25097
  * Callback when message is received
24978
25098
  */
@@ -24995,7 +25115,7 @@ var StreamableHttpServerTransport = class {
24995
25115
  return new Promise((resolve6, reject) => {
24996
25116
  this.server.listen(this.port, this.host, () => {
24997
25117
  this.started = true;
24998
- console.error(
25118
+ this.logger.error(
24999
25119
  `Streamable HTTP transport listening on http://${this.host}:${this.port}${this.endpointPath}`
25000
25120
  );
25001
25121
  resolve6();
@@ -25048,34 +25168,34 @@ var StreamableHttpServerTransport = class {
25048
25168
  * @param message JSON-RPC message
25049
25169
  */
25050
25170
  async send(message) {
25051
- console.error(`StreamableHttpServerTransport: Sending message: ${JSON.stringify(message)}`);
25171
+ this.logger.error(`StreamableHttpServerTransport: Sending message: ${JSON.stringify(message)}`);
25052
25172
  let targetSessionId;
25053
25173
  let messageIdForThisResponse = null;
25054
25174
  if (isJSONRPCResponse(message) && message.id !== null) {
25055
25175
  messageIdForThisResponse = message.id;
25056
25176
  targetSessionId = this.requestSessionMap.get(messageIdForThisResponse);
25057
- console.error(
25177
+ this.logger.error(
25058
25178
  `StreamableHttpServerTransport: Potential target session for response ID ${messageIdForThisResponse}: ${targetSessionId}`
25059
25179
  );
25060
25180
  if (targetSessionId && this.initResponseHandlers.has(targetSessionId)) {
25061
- console.error(
25181
+ this.logger.error(
25062
25182
  `StreamableHttpServerTransport: Session ${targetSessionId} has initResponseHandlers. Invoking them for message ID ${messageIdForThisResponse}.`
25063
25183
  );
25064
25184
  const handlers = this.initResponseHandlers.get(targetSessionId);
25065
25185
  [...handlers].forEach((handler) => handler(message));
25066
25186
  if (!this.requestSessionMap.has(messageIdForThisResponse)) {
25067
- console.error(
25187
+ this.logger.error(
25068
25188
  `StreamableHttpServerTransport: Response for ID ${messageIdForThisResponse} was handled by an initResponseHandler (e.g., synchronous POST response for initialize or tools/list).`
25069
25189
  );
25070
25190
  return;
25071
25191
  } else {
25072
- console.error(
25192
+ this.logger.error(
25073
25193
  `StreamableHttpServerTransport: Response for ID ${messageIdForThisResponse} was NOT exclusively handled by an initResponseHandler or handler did not remove from requestSessionMap. Proceeding to GET stream / broadcast if applicable.`
25074
25194
  );
25075
25195
  }
25076
25196
  }
25077
25197
  if (this.requestSessionMap.has(messageIdForThisResponse)) {
25078
- console.error(
25198
+ this.logger.error(
25079
25199
  `StreamableHttpServerTransport: Deleting request ID ${messageIdForThisResponse} from requestSessionMap as it's being processed for GET stream or broadcast.`
25080
25200
  );
25081
25201
  this.requestSessionMap.delete(messageIdForThisResponse);
@@ -25083,7 +25203,7 @@ var StreamableHttpServerTransport = class {
25083
25203
  }
25084
25204
  if (!targetSessionId) {
25085
25205
  const idForLog = messageIdForThisResponse !== null ? messageIdForThisResponse : isJSONRPCRequest(message) ? message.id : "N/A";
25086
- console.warn(
25206
+ this.logger.warn(
25087
25207
  `StreamableHttpServerTransport: No specific target session for message (ID: ${idForLog}). Broadcasting to all applicable sessions.`
25088
25208
  );
25089
25209
  for (const [sid, session2] of this.sessions.entries()) {
@@ -25095,12 +25215,12 @@ var StreamableHttpServerTransport = class {
25095
25215
  }
25096
25216
  const session = this.sessions.get(targetSessionId);
25097
25217
  if (session && session.activeResponses.size > 0) {
25098
- console.error(
25218
+ this.logger.error(
25099
25219
  `StreamableHttpServerTransport: Sending message (ID: ${messageIdForThisResponse}) to GET stream for session ${targetSessionId} (${session.activeResponses.size} active connections).`
25100
25220
  );
25101
25221
  this.sendMessageToSession(targetSessionId, session, message);
25102
25222
  } else if (targetSessionId) {
25103
- console.error(
25223
+ this.logger.error(
25104
25224
  `StreamableHttpServerTransport: No active GET connections for session ${targetSessionId} to send message (ID: ${messageIdForThisResponse}). Message might not be delivered if not handled by POST.`
25105
25225
  );
25106
25226
  }
@@ -25579,20 +25699,22 @@ async function loadResources(pathOrUrl, inline) {
25579
25699
 
25580
25700
  // src/index.ts
25581
25701
  async function main() {
25702
+ const logger = new Logger(true);
25582
25703
  try {
25583
25704
  const config = loadConfig();
25705
+ logger.setVerbose(config.verbose);
25584
25706
  if (config.promptsPath || config.promptsInline) {
25585
25707
  const prompts = await loadPrompts(config.promptsPath, config.promptsInline);
25586
25708
  if (prompts) {
25587
25709
  config.prompts = prompts;
25588
- console.error(`Loaded ${prompts.length} prompt(s)`);
25710
+ logger.error(`Loaded ${prompts.length} prompt(s)`);
25589
25711
  }
25590
25712
  }
25591
25713
  if (config.resourcesPath || config.resourcesInline) {
25592
25714
  const resources = await loadResources(config.resourcesPath, config.resourcesInline);
25593
25715
  if (resources) {
25594
25716
  config.resources = resources;
25595
- console.error(`Loaded ${resources.length} resource(s)`);
25717
+ logger.error(`Loaded ${resources.length} resource(s)`);
25596
25718
  }
25597
25719
  }
25598
25720
  const server = new OpenAPIServer(config);
@@ -25601,19 +25723,21 @@ async function main() {
25601
25723
  transport = new StreamableHttpServerTransport(
25602
25724
  config.httpPort,
25603
25725
  config.httpHost,
25604
- config.endpointPath
25726
+ config.endpointPath,
25727
+ void 0,
25728
+ config.verbose
25605
25729
  );
25606
25730
  await server.start(transport);
25607
- console.error(
25731
+ logger.error(
25608
25732
  `OpenAPI MCP Server running on http://${config.httpHost}:${config.httpPort}${config.endpointPath}`
25609
25733
  );
25610
25734
  } else {
25611
25735
  transport = new StdioServerTransport();
25612
25736
  await server.start(transport);
25613
- console.error("OpenAPI MCP Server running on stdio");
25737
+ logger.error("OpenAPI MCP Server running on stdio");
25614
25738
  }
25615
25739
  } catch (error) {
25616
- console.error("Failed to start server:", error);
25740
+ logger.fatal("Failed to start server:", error);
25617
25741
  process.exit(1);
25618
25742
  }
25619
25743
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ivotoby/openapi-mcp-server",
3
- "version": "1.12.5",
3
+ "version": "1.14.0",
4
4
  "description": "An MCP server that exposes OpenAPI endpoints as resources",
5
5
  "license": "MIT",
6
6
  "type": "module",