Skip to main content
Glama
masamunet

npm-dev-mcp

by masamunet

start_dev_server

Start npm development server in background for specified directory. Automatically detects projects and manages processes.

Instructions

指定ディレクトリでnpm run devをバックグラウンドで開始

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
directoryNo実行ディレクトリ(オプション、未指定時は自動検出)

Implementation Reference

  • Main tool handler: orchestrates project scanning, env loading, ProcessManager invocation, and formats response with process details and ports.
    export async function startDevServer(args: { directory?: string }): Promise<string> {
      try {
        logger.info('Starting dev server', { directory: args.directory });
    
        let targetDirectory = args.directory;
        let envPath: string | undefined;
    
        // If no directory specified, auto-detect
        if (!targetDirectory) {
          const scanner = new ProjectScanner();
          const bestProject = await scanner.findBestProject();
    
          if (!bestProject) {
            return JSON.stringify({
              success: false,
              message: 'devスクリプトが定義されたpackage.jsonが見つかりませんでした。scan_project_dirsを実行して利用可能なプロジェクトを確認してください。'
            });
          }
    
          targetDirectory = bestProject.directory;
          envPath = bestProject.envPath;
          logger.info(`Auto-detected project directory: ${targetDirectory}`);
        }
    
        // Load environment variables
        const envLoader = new EnvLoader();
        const env = await envLoader.prepareEnvironment(envPath);
    
        // Start the dev server
        const processManager = ProcessManager.getInstance();
        const devProcess = await processManager.startDevServer(targetDirectory, env);
    
        // Wait a moment to get initial status
        await new Promise(resolve => setTimeout(resolve, 2000));
        // Wait a moment to get initial status
        await new Promise(resolve => setTimeout(resolve, 2000));
        await processManager.getStatus(); // Update status/ports as side effect
    
        const result = {
          success: true,
          message: 'Dev serverが開始されました',
          process: {
            pid: devProcess.pid,
            directory: devProcess.directory,
            status: devProcess.status,
            startTime: devProcess.startTime,
            ports: devProcess.ports
          },
          environment: {
            hasEnvFile: !!envPath,
            envPath,
            nodeEnv: env.NODE_ENV || 'development'
          }
        };
    
        if (devProcess.ports.length > 0) {
          result.message += `\n起動ポート: ${devProcess.ports.join(', ')}`;
        }
    
        logger.info(`Dev server started successfully`, {
          pid: devProcess.pid,
          ports: devProcess.ports
        });
    
        return JSON.stringify(result, null, 2);
    
      } catch (error) {
        logger.error('Failed to start dev server', { error });
        return JSON.stringify({
          success: false,
          message: `Dev serverの開始に失敗しました: ${error}`,
          error: String(error)
        });
      }
    }
  • Tool schema defining name, description, and optional directory input.
    export const startDevServerSchema: Tool = {
      name: 'start_dev_server',
      description: '指定ディレクトリでnpm run devをバックグラウンドで開始',
      inputSchema: {
        type: 'object',
        properties: {
          directory: {
            type: 'string',
            description: '実行ディレクトリ(オプション、未指定時は自動検出)'
          }
        },
        additionalProperties: false
      }
    };
  • src/index.ts:137-145 (registration)
    Tool dispatch in CallToolRequestSchema handler: calls startDevServer and returns text content.
    case 'start_dev_server':
      return {
        content: [
          {
            type: 'text',
            text: await startDevServer(args as { directory?: string }),
          },
        ],
      };
  • src/index.ts:55-65 (registration)
    Registration of tool schema in the ListToolsRequestSchema response array.
    const tools = [
      scanProjectDirsSchema,
      startDevServerSchema,
      getDevStatusSchema,
      getDevLogsSchema,
      stopDevServerSchema,
      restartDevServerSchema,
      getHealthStatusSchema,
      recoverFromStateSchema,
      autoRecoverSchema,
    ];
  • Core helper function in ProcessManager that spawns 'npm run dev', manages process lifecycle, logging, port detection, and state persistence.
    async startDevServer(
      directory?: string,
      env?: Record<string, string>
    ): Promise<DevProcess> {
      // Use project context if no directory specified
      let targetDirectory = directory;
      if (!targetDirectory) {
        const contextManager = ProjectContextManager.getInstance();
        if (contextManager.isInitialized()) {
          targetDirectory = contextManager.getContext().rootDirectory;
        } else {
          targetDirectory = process.cwd();
        }
      }
    
      this.logger.info(`Starting dev server in ${targetDirectory}`);
    
      // Check if a process is already running for this directory
      const existingProcess = this.processes.get(targetDirectory);
      if (existingProcess && await this.isProcessRunning(existingProcess)) {
        this.logger.info(`Dev server is already running for ${targetDirectory}`);
        return existingProcess.info;
      }
    
      try {
        // Clean up any stale process for this directory
        if (existingProcess) {
          await this.cleanupProcess(targetDirectory);
        }
    
        // Spawn the npm run dev process
        const childProcess = spawn('npm', ['run', 'dev'], {
          cwd: targetDirectory,
          env: env || process.env,
          detached: false, // Keep attached for better control
          stdio: ['ignore', 'pipe', 'pipe']
        });
    
        const pid = childProcess.pid!;
    
        // Create properties
        const logManager = new LogManager();
    
        const processInfo: DevProcess = {
          pid,
          directory: targetDirectory,
          status: 'starting',
          startTime: new Date(),
          ports: []
        };
    
        // Store in map
        this.processes.set(targetDirectory, {
          info: processInfo,
          child: childProcess,
          logManager
        });
    
        // Start logging
        await logManager.startLogging(childProcess);
    
        // Set up process event handlers
        this.setupProcessHandlers(targetDirectory, childProcess);
    
        // Wait a moment for the process to potentially start
        await this.waitForProcessStart(targetDirectory);
    
        // Detect ports after a short delay
        setTimeout(async () => {
          const proc = this.processes.get(targetDirectory);
          if (proc) {
            proc.info.ports = await this.portDetector.getPortsByPid(pid);
            this.logger.info(`Detected ports for ${targetDirectory}: ${proc.info.ports.join(', ')}`);
            this.saveCurrentState();
          }
        }, 3000);
    
        this.logger.info(`Dev server started with PID ${pid} for ${targetDirectory}`);
        return processInfo;
    
      } catch (error) {
        this.logger.error(`Failed to start dev server for ${targetDirectory}`, { error });
        const proc = this.processes.get(targetDirectory);
        if (proc) {
          proc.info.status = 'error';
        }
        throw new Error(`Failed to start dev server: ${error}`);
      }
    }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/masamunet/npm-dev-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server