@probelabs/probe 0.6.0-rc176 → 0.6.0-rc177

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.
@@ -56110,6 +56110,12 @@ import { readFileSync, existsSync as existsSync4, mkdirSync as mkdirSync2, write
56110
56110
  import { join as join2, dirname as dirname3 } from "path";
56111
56111
  import { homedir } from "os";
56112
56112
  import { fileURLToPath as fileURLToPath6 } from "url";
56113
+ function validateTimeout(value) {
56114
+ if (value === void 0 || value === null) return void 0;
56115
+ const num = Number(value);
56116
+ if (!Number.isFinite(num) || num < 0) return void 0;
56117
+ return Math.min(num, MAX_TIMEOUT);
56118
+ }
56113
56119
  function loadMCPConfigurationFromPath(configPath) {
56114
56120
  if (!configPath) {
56115
56121
  throw new Error("Config path is required");
@@ -56195,6 +56201,14 @@ function mergeWithEnvironment(config) {
56195
56201
  config.mcpServers[normalizedName].env = { [property2]: value };
56196
56202
  }
56197
56203
  break;
56204
+ case "TIMEOUT":
56205
+ const validatedTimeout = validateTimeout(value);
56206
+ if (validatedTimeout !== void 0) {
56207
+ config.mcpServers[normalizedName].timeout = validatedTimeout;
56208
+ } else {
56209
+ console.error(`[MCP WARN] Invalid timeout value for ${normalizedName}: ${value}`);
56210
+ }
56211
+ break;
56198
56212
  }
56199
56213
  }
56200
56214
  }
@@ -56237,16 +56251,26 @@ function parseEnabledServers(config) {
56237
56251
  continue;
56238
56252
  }
56239
56253
  }
56254
+ if (server.timeout !== void 0) {
56255
+ const validatedTimeout = validateTimeout(server.timeout);
56256
+ if (validatedTimeout === void 0) {
56257
+ console.error(`[MCP ERROR] Server ${name} has invalid timeout value: ${server.timeout}`);
56258
+ continue;
56259
+ }
56260
+ server.timeout = validatedTimeout;
56261
+ }
56240
56262
  servers.push(server);
56241
56263
  }
56242
56264
  return servers;
56243
56265
  }
56244
- var __filename4, __dirname4, DEFAULT_CONFIG;
56266
+ var __filename4, __dirname4, DEFAULT_TIMEOUT, MAX_TIMEOUT, DEFAULT_CONFIG;
56245
56267
  var init_config = __esm({
56246
56268
  "src/agent/mcp/config.js"() {
56247
56269
  "use strict";
56248
56270
  __filename4 = fileURLToPath6(import.meta.url);
56249
56271
  __dirname4 = dirname3(__filename4);
56272
+ DEFAULT_TIMEOUT = 3e4;
56273
+ MAX_TIMEOUT = 6e5;
56250
56274
  DEFAULT_CONFIG = {
56251
56275
  mcpServers: {
56252
56276
  // Example probe server configuration
@@ -56475,7 +56499,9 @@ var init_client = __esm({
56475
56499
  if (this.debug) {
56476
56500
  console.error(`[MCP DEBUG] Calling ${toolName} with args:`, JSON.stringify(args, null, 2));
56477
56501
  }
56478
- const timeout = this.config?.settings?.timeout || 3e4;
56502
+ const serverTimeout = clientInfo.config?.timeout;
56503
+ const globalTimeout = this.config?.settings?.timeout ?? DEFAULT_TIMEOUT;
56504
+ const timeout = serverTimeout ?? globalTimeout;
56479
56505
  const timeoutPromise = new Promise((_, reject2) => {
56480
56506
  setTimeout(() => {
56481
56507
  reject2(new Error(`MCP tool call timeout after ${timeout}ms`));
@@ -7,7 +7,7 @@ import { Client } from '@modelcontextprotocol/sdk/client/index.js';
7
7
  import { StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js';
8
8
  import { SSEClientTransport } from '@modelcontextprotocol/sdk/client/sse.js';
9
9
  import { WebSocketClientTransport } from '@modelcontextprotocol/sdk/client/websocket.js';
10
- import { loadMCPConfiguration, parseEnabledServers } from './config.js';
10
+ import { loadMCPConfiguration, parseEnabledServers, DEFAULT_TIMEOUT } from './config.js';
11
11
 
12
12
  /**
13
13
  * Create transport based on configuration
@@ -274,8 +274,11 @@ export class MCPClientManager {
274
274
  console.error(`[MCP DEBUG] Calling ${toolName} with args:`, JSON.stringify(args, null, 2));
275
275
  }
276
276
 
277
- // Get timeout from config (default 30 seconds)
278
- const timeout = this.config?.settings?.timeout || 30000;
277
+ // Get timeout: per-server timeout takes priority over global timeout (default 30 seconds)
278
+ // Note: Timeout values are already validated at config load time by parseEnabledServers
279
+ const serverTimeout = clientInfo.config?.timeout;
280
+ const globalTimeout = this.config?.settings?.timeout ?? DEFAULT_TIMEOUT;
281
+ const timeout = serverTimeout ?? globalTimeout;
279
282
 
280
283
  // Create a timeout promise
281
284
  const timeoutPromise = new Promise((_, reject) => {
@@ -11,6 +11,24 @@ import { fileURLToPath } from 'url';
11
11
  const __filename = fileURLToPath(import.meta.url);
12
12
  const __dirname = dirname(__filename);
13
13
 
14
+ /**
15
+ * Timeout configuration constants
16
+ */
17
+ export const DEFAULT_TIMEOUT = 30000; // 30 seconds
18
+ export const MAX_TIMEOUT = 600000; // 10 minutes max to prevent resource exhaustion
19
+
20
+ /**
21
+ * Validate and normalize a timeout value
22
+ * @param {*} value - The timeout value to validate
23
+ * @returns {number|undefined} Validated timeout in ms, or undefined if invalid
24
+ */
25
+ export function validateTimeout(value) {
26
+ if (value === undefined || value === null) return undefined;
27
+ const num = Number(value);
28
+ if (!Number.isFinite(num) || num < 0) return undefined; // Invalid, use fallback
29
+ return Math.min(num, MAX_TIMEOUT); // Cap at max timeout
30
+ }
31
+
14
32
  /**
15
33
  * Default MCP configuration structure
16
34
  */
@@ -160,6 +178,15 @@ function mergeWithEnvironment(config) {
160
178
  config.mcpServers[normalizedName].env = { [property]: value };
161
179
  }
162
180
  break;
181
+ case 'TIMEOUT':
182
+ // Per-server timeout in milliseconds with validation
183
+ const validatedTimeout = validateTimeout(value);
184
+ if (validatedTimeout !== undefined) {
185
+ config.mcpServers[normalizedName].timeout = validatedTimeout;
186
+ } else {
187
+ console.error(`[MCP WARN] Invalid timeout value for ${normalizedName}: ${value}`);
188
+ }
189
+ break;
163
190
  }
164
191
  }
165
192
  }
@@ -219,6 +246,16 @@ export function parseEnabledServers(config) {
219
246
  }
220
247
  }
221
248
 
249
+ // Validate and normalize timeout if present (fail-fast validation)
250
+ if (server.timeout !== undefined) {
251
+ const validatedTimeout = validateTimeout(server.timeout);
252
+ if (validatedTimeout === undefined) {
253
+ console.error(`[MCP ERROR] Server ${name} has invalid timeout value: ${server.timeout}`);
254
+ continue;
255
+ }
256
+ server.timeout = validatedTimeout;
257
+ }
258
+
222
259
  servers.push(server);
223
260
  }
224
261
 
@@ -276,9 +313,17 @@ export function createSampleConfig() {
276
313
  transport: 'websocket',
277
314
  enabled: false,
278
315
  description: 'Custom WebSocket MCP server'
316
+ },
317
+ 'slow-server-example': {
318
+ command: 'node',
319
+ args: ['path/to/slow-server.js'],
320
+ transport: 'stdio',
321
+ enabled: false,
322
+ timeout: 120000,
323
+ description: 'Example server with custom 2-minute timeout (overrides global setting)'
279
324
  }
280
325
  },
281
- // Global settings
326
+ // Global settings (apply to all servers unless overridden per-server)
282
327
  settings: {
283
328
  timeout: 30000,
284
329
  retryCount: 3,
@@ -309,5 +354,8 @@ export default {
309
354
  loadMCPConfigurationFromPath,
310
355
  parseEnabledServers,
311
356
  createSampleConfig,
312
- saveConfig
357
+ saveConfig,
358
+ validateTimeout,
359
+ DEFAULT_TIMEOUT,
360
+ MAX_TIMEOUT
313
361
  };
@@ -5842,7 +5842,6 @@ var init_EventStreamSerde = __esm({
5842
5842
  const { eventHeader, eventPayload } = memberSchema.getMergedTraits();
5843
5843
  if (eventPayload) {
5844
5844
  explicitPayloadMember = memberName;
5845
- break;
5846
5845
  } else if (eventHeader) {
5847
5846
  const value = event[unionMember][memberName];
5848
5847
  let type = "binary";
@@ -17253,9 +17252,9 @@ var require_dist_cjs49 = __commonJS({
17253
17252
  expiration: new Date(creds.Expiration),
17254
17253
  ...creds.AccountId && { accountId: creds.AccountId }
17255
17254
  });
17256
- var DEFAULT_TIMEOUT = 1e3;
17255
+ var DEFAULT_TIMEOUT2 = 1e3;
17257
17256
  var DEFAULT_MAX_RETRIES = 0;
17258
- var providerConfigFromInit = ({ maxRetries = DEFAULT_MAX_RETRIES, timeout = DEFAULT_TIMEOUT }) => ({ maxRetries, timeout });
17257
+ var providerConfigFromInit = ({ maxRetries = DEFAULT_MAX_RETRIES, timeout = DEFAULT_TIMEOUT2 }) => ({ maxRetries, timeout });
17259
17258
  var retry = (toRetry, maxRetries) => {
17260
17259
  let promise = toRetry();
17261
17260
  for (let i4 = 0; i4 < maxRetries; i4++) {
@@ -17536,7 +17535,7 @@ For more information, please visit: ` + STATIC_STABILITY_DOC_URL);
17536
17535
  return fromImdsCredentials(credentialsResponse);
17537
17536
  };
17538
17537
  exports2.DEFAULT_MAX_RETRIES = DEFAULT_MAX_RETRIES;
17539
- exports2.DEFAULT_TIMEOUT = DEFAULT_TIMEOUT;
17538
+ exports2.DEFAULT_TIMEOUT = DEFAULT_TIMEOUT2;
17540
17539
  exports2.ENV_CMDS_AUTH_TOKEN = ENV_CMDS_AUTH_TOKEN;
17541
17540
  exports2.ENV_CMDS_FULL_URI = ENV_CMDS_FULL_URI;
17542
17541
  exports2.ENV_CMDS_RELATIVE_URI = ENV_CMDS_RELATIVE_URI;
@@ -81986,6 +81985,12 @@ You should be:
81986
81985
  });
81987
81986
 
81988
81987
  // src/agent/mcp/config.js
81988
+ function validateTimeout(value) {
81989
+ if (value === void 0 || value === null) return void 0;
81990
+ const num = Number(value);
81991
+ if (!Number.isFinite(num) || num < 0) return void 0;
81992
+ return Math.min(num, MAX_TIMEOUT);
81993
+ }
81989
81994
  function loadMCPConfigurationFromPath(configPath) {
81990
81995
  if (!configPath) {
81991
81996
  throw new Error("Config path is required");
@@ -82071,6 +82076,14 @@ function mergeWithEnvironment(config) {
82071
82076
  config.mcpServers[normalizedName].env = { [property2]: value };
82072
82077
  }
82073
82078
  break;
82079
+ case "TIMEOUT":
82080
+ const validatedTimeout = validateTimeout(value);
82081
+ if (validatedTimeout !== void 0) {
82082
+ config.mcpServers[normalizedName].timeout = validatedTimeout;
82083
+ } else {
82084
+ console.error(`[MCP WARN] Invalid timeout value for ${normalizedName}: ${value}`);
82085
+ }
82086
+ break;
82074
82087
  }
82075
82088
  }
82076
82089
  }
@@ -82113,11 +82126,19 @@ function parseEnabledServers(config) {
82113
82126
  continue;
82114
82127
  }
82115
82128
  }
82129
+ if (server.timeout !== void 0) {
82130
+ const validatedTimeout = validateTimeout(server.timeout);
82131
+ if (validatedTimeout === void 0) {
82132
+ console.error(`[MCP ERROR] Server ${name14} has invalid timeout value: ${server.timeout}`);
82133
+ continue;
82134
+ }
82135
+ server.timeout = validatedTimeout;
82136
+ }
82116
82137
  servers.push(server);
82117
82138
  }
82118
82139
  return servers;
82119
82140
  }
82120
- var import_fs12, import_path11, import_os3, import_url4, __filename4, __dirname4, DEFAULT_CONFIG;
82141
+ var import_fs12, import_path11, import_os3, import_url4, __filename4, __dirname4, DEFAULT_TIMEOUT, MAX_TIMEOUT, DEFAULT_CONFIG;
82121
82142
  var init_config = __esm({
82122
82143
  "src/agent/mcp/config.js"() {
82123
82144
  "use strict";
@@ -82127,6 +82148,8 @@ var init_config = __esm({
82127
82148
  import_url4 = require("url");
82128
82149
  __filename4 = (0, import_url4.fileURLToPath)("file:///");
82129
82150
  __dirname4 = (0, import_path11.dirname)(__filename4);
82151
+ DEFAULT_TIMEOUT = 3e4;
82152
+ MAX_TIMEOUT = 6e5;
82130
82153
  DEFAULT_CONFIG = {
82131
82154
  mcpServers: {
82132
82155
  // Example probe server configuration
@@ -82355,7 +82378,9 @@ var init_client2 = __esm({
82355
82378
  if (this.debug) {
82356
82379
  console.error(`[MCP DEBUG] Calling ${toolName} with args:`, JSON.stringify(args, null, 2));
82357
82380
  }
82358
- const timeout = this.config?.settings?.timeout || 3e4;
82381
+ const serverTimeout = clientInfo.config?.timeout;
82382
+ const globalTimeout = this.config?.settings?.timeout ?? DEFAULT_TIMEOUT;
82383
+ const timeout = serverTimeout ?? globalTimeout;
82359
82384
  const timeoutPromise = new Promise((_, reject2) => {
82360
82385
  setTimeout(() => {
82361
82386
  reject2(new Error(`MCP tool call timeout after ${timeout}ms`));
package/cjs/index.cjs CHANGED
@@ -7369,7 +7369,6 @@ var init_EventStreamSerde = __esm({
7369
7369
  const { eventHeader, eventPayload } = memberSchema.getMergedTraits();
7370
7370
  if (eventPayload) {
7371
7371
  explicitPayloadMember = memberName;
7372
- break;
7373
7372
  } else if (eventHeader) {
7374
7373
  const value = event[unionMember][memberName];
7375
7374
  let type = "binary";
@@ -18780,9 +18779,9 @@ var require_dist_cjs49 = __commonJS({
18780
18779
  expiration: new Date(creds.Expiration),
18781
18780
  ...creds.AccountId && { accountId: creds.AccountId }
18782
18781
  });
18783
- var DEFAULT_TIMEOUT = 1e3;
18782
+ var DEFAULT_TIMEOUT2 = 1e3;
18784
18783
  var DEFAULT_MAX_RETRIES = 0;
18785
- var providerConfigFromInit = ({ maxRetries = DEFAULT_MAX_RETRIES, timeout = DEFAULT_TIMEOUT }) => ({ maxRetries, timeout });
18784
+ var providerConfigFromInit = ({ maxRetries = DEFAULT_MAX_RETRIES, timeout = DEFAULT_TIMEOUT2 }) => ({ maxRetries, timeout });
18786
18785
  var retry = (toRetry, maxRetries) => {
18787
18786
  let promise = toRetry();
18788
18787
  for (let i4 = 0; i4 < maxRetries; i4++) {
@@ -19063,7 +19062,7 @@ For more information, please visit: ` + STATIC_STABILITY_DOC_URL);
19063
19062
  return fromImdsCredentials(credentialsResponse);
19064
19063
  };
19065
19064
  exports2.DEFAULT_MAX_RETRIES = DEFAULT_MAX_RETRIES;
19066
- exports2.DEFAULT_TIMEOUT = DEFAULT_TIMEOUT;
19065
+ exports2.DEFAULT_TIMEOUT = DEFAULT_TIMEOUT2;
19067
19066
  exports2.ENV_CMDS_AUTH_TOKEN = ENV_CMDS_AUTH_TOKEN;
19068
19067
  exports2.ENV_CMDS_FULL_URI = ENV_CMDS_FULL_URI;
19069
19068
  exports2.ENV_CMDS_RELATIVE_URI = ENV_CMDS_RELATIVE_URI;
@@ -79717,6 +79716,12 @@ You should be:
79717
79716
  });
79718
79717
 
79719
79718
  // src/agent/mcp/config.js
79719
+ function validateTimeout(value) {
79720
+ if (value === void 0 || value === null) return void 0;
79721
+ const num = Number(value);
79722
+ if (!Number.isFinite(num) || num < 0) return void 0;
79723
+ return Math.min(num, MAX_TIMEOUT);
79724
+ }
79720
79725
  function loadMCPConfigurationFromPath(configPath) {
79721
79726
  if (!configPath) {
79722
79727
  throw new Error("Config path is required");
@@ -79802,6 +79807,14 @@ function mergeWithEnvironment(config) {
79802
79807
  config.mcpServers[normalizedName].env = { [property2]: value };
79803
79808
  }
79804
79809
  break;
79810
+ case "TIMEOUT":
79811
+ const validatedTimeout = validateTimeout(value);
79812
+ if (validatedTimeout !== void 0) {
79813
+ config.mcpServers[normalizedName].timeout = validatedTimeout;
79814
+ } else {
79815
+ console.error(`[MCP WARN] Invalid timeout value for ${normalizedName}: ${value}`);
79816
+ }
79817
+ break;
79805
79818
  }
79806
79819
  }
79807
79820
  }
@@ -79844,11 +79857,19 @@ function parseEnabledServers(config) {
79844
79857
  continue;
79845
79858
  }
79846
79859
  }
79860
+ if (server.timeout !== void 0) {
79861
+ const validatedTimeout = validateTimeout(server.timeout);
79862
+ if (validatedTimeout === void 0) {
79863
+ console.error(`[MCP ERROR] Server ${name14} has invalid timeout value: ${server.timeout}`);
79864
+ continue;
79865
+ }
79866
+ server.timeout = validatedTimeout;
79867
+ }
79847
79868
  servers.push(server);
79848
79869
  }
79849
79870
  return servers;
79850
79871
  }
79851
- var import_fs7, import_path6, import_os3, import_url4, __filename4, __dirname4, DEFAULT_CONFIG;
79872
+ var import_fs7, import_path6, import_os3, import_url4, __filename4, __dirname4, DEFAULT_TIMEOUT, MAX_TIMEOUT, DEFAULT_CONFIG;
79852
79873
  var init_config = __esm({
79853
79874
  "src/agent/mcp/config.js"() {
79854
79875
  "use strict";
@@ -79858,6 +79879,8 @@ var init_config = __esm({
79858
79879
  import_url4 = require("url");
79859
79880
  __filename4 = (0, import_url4.fileURLToPath)("file:///");
79860
79881
  __dirname4 = (0, import_path6.dirname)(__filename4);
79882
+ DEFAULT_TIMEOUT = 3e4;
79883
+ MAX_TIMEOUT = 6e5;
79861
79884
  DEFAULT_CONFIG = {
79862
79885
  mcpServers: {
79863
79886
  // Example probe server configuration
@@ -80086,7 +80109,9 @@ var init_client2 = __esm({
80086
80109
  if (this.debug) {
80087
80110
  console.error(`[MCP DEBUG] Calling ${toolName} with args:`, JSON.stringify(args, null, 2));
80088
80111
  }
80089
- const timeout = this.config?.settings?.timeout || 3e4;
80112
+ const serverTimeout = clientInfo.config?.timeout;
80113
+ const globalTimeout = this.config?.settings?.timeout ?? DEFAULT_TIMEOUT;
80114
+ const timeout = serverTimeout ?? globalTimeout;
80090
80115
  const timeoutPromise = new Promise((_, reject2) => {
80091
80116
  setTimeout(() => {
80092
80117
  reject2(new Error(`MCP tool call timeout after ${timeout}ms`));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@probelabs/probe",
3
- "version": "0.6.0-rc176",
3
+ "version": "0.6.0-rc177",
4
4
  "description": "Node.js wrapper for the probe code search tool",
5
5
  "main": "src/index.js",
6
6
  "module": "src/index.js",
@@ -7,7 +7,7 @@ import { Client } from '@modelcontextprotocol/sdk/client/index.js';
7
7
  import { StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js';
8
8
  import { SSEClientTransport } from '@modelcontextprotocol/sdk/client/sse.js';
9
9
  import { WebSocketClientTransport } from '@modelcontextprotocol/sdk/client/websocket.js';
10
- import { loadMCPConfiguration, parseEnabledServers } from './config.js';
10
+ import { loadMCPConfiguration, parseEnabledServers, DEFAULT_TIMEOUT } from './config.js';
11
11
 
12
12
  /**
13
13
  * Create transport based on configuration
@@ -274,8 +274,11 @@ export class MCPClientManager {
274
274
  console.error(`[MCP DEBUG] Calling ${toolName} with args:`, JSON.stringify(args, null, 2));
275
275
  }
276
276
 
277
- // Get timeout from config (default 30 seconds)
278
- const timeout = this.config?.settings?.timeout || 30000;
277
+ // Get timeout: per-server timeout takes priority over global timeout (default 30 seconds)
278
+ // Note: Timeout values are already validated at config load time by parseEnabledServers
279
+ const serverTimeout = clientInfo.config?.timeout;
280
+ const globalTimeout = this.config?.settings?.timeout ?? DEFAULT_TIMEOUT;
281
+ const timeout = serverTimeout ?? globalTimeout;
279
282
 
280
283
  // Create a timeout promise
281
284
  const timeoutPromise = new Promise((_, reject) => {
@@ -11,6 +11,24 @@ import { fileURLToPath } from 'url';
11
11
  const __filename = fileURLToPath(import.meta.url);
12
12
  const __dirname = dirname(__filename);
13
13
 
14
+ /**
15
+ * Timeout configuration constants
16
+ */
17
+ export const DEFAULT_TIMEOUT = 30000; // 30 seconds
18
+ export const MAX_TIMEOUT = 600000; // 10 minutes max to prevent resource exhaustion
19
+
20
+ /**
21
+ * Validate and normalize a timeout value
22
+ * @param {*} value - The timeout value to validate
23
+ * @returns {number|undefined} Validated timeout in ms, or undefined if invalid
24
+ */
25
+ export function validateTimeout(value) {
26
+ if (value === undefined || value === null) return undefined;
27
+ const num = Number(value);
28
+ if (!Number.isFinite(num) || num < 0) return undefined; // Invalid, use fallback
29
+ return Math.min(num, MAX_TIMEOUT); // Cap at max timeout
30
+ }
31
+
14
32
  /**
15
33
  * Default MCP configuration structure
16
34
  */
@@ -160,6 +178,15 @@ function mergeWithEnvironment(config) {
160
178
  config.mcpServers[normalizedName].env = { [property]: value };
161
179
  }
162
180
  break;
181
+ case 'TIMEOUT':
182
+ // Per-server timeout in milliseconds with validation
183
+ const validatedTimeout = validateTimeout(value);
184
+ if (validatedTimeout !== undefined) {
185
+ config.mcpServers[normalizedName].timeout = validatedTimeout;
186
+ } else {
187
+ console.error(`[MCP WARN] Invalid timeout value for ${normalizedName}: ${value}`);
188
+ }
189
+ break;
163
190
  }
164
191
  }
165
192
  }
@@ -219,6 +246,16 @@ export function parseEnabledServers(config) {
219
246
  }
220
247
  }
221
248
 
249
+ // Validate and normalize timeout if present (fail-fast validation)
250
+ if (server.timeout !== undefined) {
251
+ const validatedTimeout = validateTimeout(server.timeout);
252
+ if (validatedTimeout === undefined) {
253
+ console.error(`[MCP ERROR] Server ${name} has invalid timeout value: ${server.timeout}`);
254
+ continue;
255
+ }
256
+ server.timeout = validatedTimeout;
257
+ }
258
+
222
259
  servers.push(server);
223
260
  }
224
261
 
@@ -276,9 +313,17 @@ export function createSampleConfig() {
276
313
  transport: 'websocket',
277
314
  enabled: false,
278
315
  description: 'Custom WebSocket MCP server'
316
+ },
317
+ 'slow-server-example': {
318
+ command: 'node',
319
+ args: ['path/to/slow-server.js'],
320
+ transport: 'stdio',
321
+ enabled: false,
322
+ timeout: 120000,
323
+ description: 'Example server with custom 2-minute timeout (overrides global setting)'
279
324
  }
280
325
  },
281
- // Global settings
326
+ // Global settings (apply to all servers unless overridden per-server)
282
327
  settings: {
283
328
  timeout: 30000,
284
329
  retryCount: 3,
@@ -309,5 +354,8 @@ export default {
309
354
  loadMCPConfigurationFromPath,
310
355
  parseEnabledServers,
311
356
  createSampleConfig,
312
- saveConfig
357
+ saveConfig,
358
+ validateTimeout,
359
+ DEFAULT_TIMEOUT,
360
+ MAX_TIMEOUT
313
361
  };