@maplezzk/mcps 1.1.0 → 1.1.2

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.
@@ -26,6 +26,14 @@ function isPortInUse(port) {
26
26
  // Action functions for daemon commands
27
27
  const startAction = async (options) => {
28
28
  const port = parseInt(options.port || process.env.MCPS_PORT || DAEMON_PORT);
29
+ // Get timeout from option, env, or config (in seconds)
30
+ let timeout = 30; // Default 30 seconds for daemon start
31
+ if (options.timeout) {
32
+ timeout = parseInt(options.timeout, 10);
33
+ }
34
+ else if (process.env.MCPS_DAEMON_TIMEOUT) {
35
+ timeout = parseInt(process.env.MCPS_DAEMON_TIMEOUT, 10);
36
+ }
29
37
  // Check if port is in use (more reliable than HTTP check)
30
38
  const portInUse = await isPortInUse(port);
31
39
  if (portInUse) {
@@ -86,8 +94,8 @@ const startAction = async (options) => {
86
94
  // Wait briefly to ensure it started (optional but good UX)
87
95
  // We can poll status for a second
88
96
  const start = Date.now();
89
- // Increased timeout to allow for connection initialization
90
- while (Date.now() - start < 30000) {
97
+ // Use timeout from option/env (convert to ms)
98
+ while (Date.now() - start < timeout * 1000) {
91
99
  // If child reported port conflict, check if daemon is actually running
92
100
  if (childFailed) {
93
101
  const stillRunning = await isPortInUse(port);
@@ -204,6 +212,7 @@ export const registerDaemonCommand = (program) => {
204
212
  program.command('start')
205
213
  .description('Start the daemon')
206
214
  .option('-p, --port <number>', 'Daemon port', String(DAEMON_PORT))
215
+ .option('-t, --timeout <seconds>', 'Startup timeout in seconds (default: 30)')
207
216
  .option('-v, --verbose', 'Show detailed logs')
208
217
  .action((options) => startAction(options));
209
218
  program.command('stop')
@@ -225,6 +234,7 @@ export const registerDaemonCommand = (program) => {
225
234
  .option('-p, --port <number>', 'Daemon port', String(DAEMON_PORT));
226
235
  daemonCmd.command('start', { isDefault: true, hidden: true })
227
236
  .description('Start the daemon (default)')
237
+ .option('-t, --timeout <seconds>', 'Startup timeout in seconds (default: 30)')
228
238
  .action((options) => startAction(options));
229
239
  daemonCmd.command('stop')
230
240
  .description('Stop the running daemon')
@@ -98,5 +98,20 @@ export class ConfigManager {
98
98
  config.mcpServers[name] = result.data;
99
99
  this.saveConfig(config);
100
100
  }
101
+ getDaemonTimeout() {
102
+ // Priority: environment variable > config file > default
103
+ const envTimeout = process.env.MCPS_DAEMON_TIMEOUT;
104
+ if (envTimeout) {
105
+ const parsed = parseInt(envTimeout, 10);
106
+ if (!isNaN(parsed) && parsed > 0) {
107
+ return parsed * 1000; // Convert seconds to milliseconds
108
+ }
109
+ }
110
+ const config = this.loadConfig();
111
+ if (config.daemonTimeout) {
112
+ return config.daemonTimeout;
113
+ }
114
+ return 20000; // Default 20 seconds
115
+ }
101
116
  }
102
117
  export const configManager = new ConfigManager();
@@ -1,6 +1,7 @@
1
1
  import { spawn } from 'child_process';
2
2
  import chalk from 'chalk';
3
3
  import { DAEMON_BASE_URL } from './constants.js';
4
+ import { configManager } from './config.js';
4
5
  export class DaemonClient {
5
6
  static async isRunning() {
6
7
  try {
@@ -11,8 +12,10 @@ export class DaemonClient {
11
12
  return false;
12
13
  }
13
14
  }
14
- static async startDaemon() {
15
+ static async startDaemon(timeout) {
15
16
  console.log(chalk.gray('Starting background daemon...'));
17
+ // Get timeout from parameter or config
18
+ const daemonTimeout = timeout || configManager.getDaemonTimeout();
16
19
  // Use process.argv[1] which points to the CLI entry point
17
20
  // detached: true allows the child to keep running after parent exits
18
21
  const subprocess = spawn(process.execPath, [process.argv[1], 'daemon', 'start'], {
@@ -23,19 +26,19 @@ export class DaemonClient {
23
26
  subprocess.unref();
24
27
  // Wait for daemon to be ready
25
28
  const start = Date.now();
26
- while (Date.now() - start < 5000) { // 5s timeout
29
+ while (Date.now() - start < daemonTimeout) {
27
30
  if (await this.isRunning()) {
28
31
  return;
29
32
  }
30
33
  await new Promise(resolve => setTimeout(resolve, 200));
31
34
  }
32
- throw new Error('Daemon failed to start within timeout');
35
+ throw new Error(`Daemon failed to start within ${daemonTimeout / 1000}s timeout`);
33
36
  }
34
- static async ensureDaemon() {
37
+ static async ensureDaemon(timeout) {
35
38
  if (await this.isRunning()) {
36
39
  return;
37
40
  }
38
- await this.startDaemon();
41
+ await this.startDaemon(timeout);
39
42
  }
40
43
  static async executeTool(serverName, toolName, args) {
41
44
  const response = await fetch(`${DAEMON_BASE_URL}/call`, {
@@ -22,6 +22,7 @@ export const ServerConfigSchema = z.union([
22
22
  // Standard MCP config format (mcpServers)
23
23
  export const ConfigSchema = z.object({
24
24
  mcpServers: z.record(z.string(), ServerConfigSchema),
25
+ daemonTimeout: z.number().optional(),
25
26
  });
26
27
  // Helper to detect server type from config
27
28
  export function detectServerType(config) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@maplezzk/mcps",
3
- "version": "1.1.0",
3
+ "version": "1.1.2",
4
4
  "description": "A CLI to manage and use MCP servers",
5
5
  "publishConfig": {
6
6
  "access": "public"