rolldev_stop_svc
Stop RollDev system services for a specified project directory to halt development environments.
Instructions
Stop RollDev system services
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| project_path | Yes | Path to the project directory |
Implementation Reference
- server.js:545-552 (handler)Handler function for rolldev_stop_svc - executes 'roll svc down' command via executeRollCommand helper.
async stopSvc(args) { const { project_path } = args; return await this.executeRollCommand( project_path, ["svc", "down"], "Stopping RollDev system services", ); } - server.js:142-154 (registration)Tool registration: defines name 'rolldev_stop_svc', description 'Stop RollDev system services', and inputSchema with required project_path string.
name: "rolldev_stop_svc", description: "Stop RollDev system services", inputSchema: { type: "object", properties: { project_path: { type: "string", description: "Path to the project directory", }, }, required: ["project_path"], }, }, - server.js:303-304 (registration)Switch case routing the tool name 'rolldev_stop_svc' to stopSvc handler.
case "rolldev_stop_svc": return await this.stopSvc(request.params.arguments); - server.js:742-857 (helper)executeRollCommand helper - executes a 'roll' CLI command with args, handles success/failure, returns formatted text response.
async executeRollCommand(project_path, rollArgs, description, timeoutMs = 300000, saveToFile = false) { if (!project_path) { throw new Error("project_path is required"); } const normalizedProjectPath = project_path.replace(/\/+$/, ""); const absoluteProjectPath = resolve(normalizedProjectPath); if (!existsSync(absoluteProjectPath)) { throw new Error( `Project directory does not exist: ${absoluteProjectPath}`, ); } try { const result = await this.executeCommand( "roll", rollArgs, absoluteProjectPath, timeoutMs, ); const commandStr = `roll ${rollArgs.join(" ")}`; const isSuccess = result.code === 0; // Save output to file only when explicitly requested const logFilePath = saveToFile ? this.saveOutputToFile(result.stdout, result.stderr, commandStr, absoluteProjectPath) : null; let responseText; if (logFilePath) { // Output saved to file const outputPreview = (result.stdout || "").substring(0, 500); const stderrPreview = (result.stderr || "").substring(0, 500); responseText = `${description} ${isSuccess ? "completed successfully" : "failed"}! Command: ${commandStr} Working directory: ${absoluteProjectPath} Exit Code: ${result.code}${result.timedOut ? " (TIMED OUT)" : ""} 📁 Full output saved to file: ${logFilePath} Output Preview (first 500 chars): ${outputPreview || "(no output)"}${(result.stdout || "").length > 500 ? "\n...(truncated)" : ""} Errors Preview (first 500 chars): ${stderrPreview || "(no errors)"}${(result.stderr || "").length > 500 ? "\n...(truncated)" : ""}`; } else { // Return inline output responseText = `${description} ${isSuccess ? "completed successfully" : "failed"}! Command: ${commandStr} Working directory: ${absoluteProjectPath} Exit Code: ${result.code}${result.timedOut ? " (TIMED OUT)" : ""} Output: ${result.stdout || "(no output)"} Errors: ${result.stderr || "(no errors)"}`; } return { content: [ { type: "text", text: responseText, }, ], isError: !isSuccess, }; } catch (error) { const commandStr = `roll ${rollArgs.join(" ")}`; // Save error output to file only when explicitly requested const logFilePath = saveToFile ? this.saveOutputToFile(error.stdout, error.stderr, commandStr, absoluteProjectPath) : null; let responseText; if (logFilePath) { responseText = `Failed to execute command: Command: ${commandStr} Working directory: ${absoluteProjectPath} Error: ${error.message} 📁 Full output saved to file: ${logFilePath}`; } else { responseText = `Failed to execute command: Command: ${commandStr} Working directory: ${absoluteProjectPath} Error: ${error.message} Output: ${error.stdout || "(no output)"} Errors: ${error.stderr || "(no errors)"}`; } return { content: [ { type: "text", text: responseText, }, ], isError: true, }; } } - server.js:933-1008 (helper)executeCommand helper - spawns a child process, collects stdout/stderr, handles timeouts with SIGTERM/SIGKILL.
executeCommand(command, args = [], cwd = process.cwd(), timeoutMs = 300000) { return new Promise((resolve, reject) => { const childProcess = spawn(command, args, { cwd, stdio: ["pipe", "pipe", "pipe"], }); let stdout = ""; let stderr = ""; let resolved = false; // Helper to resolve only once const resolveOnce = (result) => { if (!resolved) { resolved = true; clearTimeout(timeout); resolve(result); } }; const rejectOnce = (error) => { if (!resolved) { resolved = true; clearTimeout(timeout); reject(error); } }; // Timeout handler const timeout = setTimeout(() => { if (!resolved) { // Try graceful termination first childProcess.kill('SIGTERM'); // Force kill after 5 seconds if still running setTimeout(() => { if (!resolved) { childProcess.kill('SIGKILL'); } }, 5000); resolveOnce({ stdout, stderr: stderr + `\n[Command timed out after ${timeoutMs / 1000}s]`, code: -1, timedOut: true, }); } }, timeoutMs); childProcess.stdout.on("data", (data) => { stdout += data.toString(); }); childProcess.stderr.on("data", (data) => { stderr += data.toString(); }); childProcess.on("close", (code) => { resolveOnce({ stdout, stderr, code }); }); // Also listen to 'exit' as backup (some processes emit exit but not close) childProcess.on("exit", (code) => { resolveOnce({ stdout, stderr, code }); }); childProcess.on("error", (error) => { const enhancedError = new Error( `Failed to spawn command: ${error.message}`, ); enhancedError.stdout = stdout; enhancedError.stderr = stderr; rejectOnce(enhancedError); }); });