rolldev_list_environments
Lists all active RollDev environments and their directories, returning structured JSON for environment management and monitoring.
Instructions
List all running RollDev environments with their directories (returns structured JSON)
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
No arguments | |||
Implementation Reference
- server.js:86-98 (registration)Tool registration: 'rolldev_list_environments' is registered as a ListTools handler with no required input schema.
this.server.setRequestHandler(ListToolsRequestSchema, async () => { return { tools: [ { name: "rolldev_list_environments", description: "List all running RollDev environments with their directories (returns structured JSON)", inputSchema: { type: "object", properties: {}, required: [], }, }, - server.js:293-296 (handler)Handler dispatch: the CallToolRequestSchema routes 'rolldev_list_environments' to this.listEnvironments()
this.server.setRequestHandler(CallToolRequestSchema, async (request) => { switch (request.params.name) { case "rolldev_list_environments": return await this.listEnvironments(); - server.js:322-403 (handler)Core handler: listEnvironments() executes 'roll status' command, parses output, and returns structured JSON with environment details (name, path, url, network, containers).
async listEnvironments() { try { const result = await this.executeCommand( "roll", ["status"], process.cwd(), ); if (result.code === 0) { const environments = this.parseEnvironmentList(result.stdout); return { content: [ { type: "text", text: JSON.stringify( { success: true, command: "roll status", exit_code: result.code, environments: environments.map((env) => ({ name: env.name, path: env.path, url: env.url, network: env.network, containers: env.containers, })), raw_output: result.stdout, }, null, 2, ), }, ], isError: false, }; } else { return { content: [ { type: "text", text: JSON.stringify( { success: false, command: "roll status", exit_code: result.code, environments: [], error: result.stderr || "Unknown error", raw_output: result.stdout, }, null, 2, ), }, ], isError: true, }; } } catch (error) { return { content: [ { type: "text", text: JSON.stringify( { success: false, command: "roll status", exit_code: -1, environments: [], error: error.message, raw_output: error.stdout || "", raw_errors: error.stderr || "", }, null, 2, ), }, ], isError: true, }; } } - server.js:405-490 (helper)Helper: parseEnvironmentList() parses the raw 'roll status' output line-by-line, extracting project names, directories, URLs, networks, and container counts.
parseEnvironmentList(output) { const environments = []; const lines = output.split("\n"); let currentProject = null; let currentPath = null; let currentUrl = null; let currentNetwork = null; let currentContainers = null; for (const line of lines) { const trimmed = line.trim(); // Skip empty lines and headers if ( !trimmed || trimmed.includes("No running environments found") || trimmed.includes("Found the following") || trimmed.includes("RollDev Services") ) { continue; } // Remove ANSI color codes for parsing const cleanLine = trimmed.replace(/\x1b\[[0-9;]*m/g, ""); // Look for project name pattern: "ai-demo a magento2 project" const projectMatch = cleanLine.match(/^(\S+)\s+a\s+(\w+)\s+project$/); if (projectMatch) { currentProject = projectMatch[1]; continue; } // Look for project directory pattern: "Project Directory: /path/to/project" const directoryMatch = cleanLine.match(/^\s*Project Directory:\s*(.+)$/); if (directoryMatch) { currentPath = directoryMatch[1]; continue; } // Look for project URL pattern: "Project URL: https://app.ai-demo.test" const urlMatch = cleanLine.match(/^\s*Project URL:\s*(.+)$/); if (urlMatch) { currentUrl = urlMatch[1]; continue; } // Look for docker network pattern: "Docker Network: ai-demo_default" const networkMatch = cleanLine.match(/^\s*Docker Network:\s*(.+)$/); if (networkMatch) { currentNetwork = networkMatch[1]; continue; } // Look for containers running pattern: "Containers Running: 9" const containersMatch = cleanLine.match(/^\s*Containers Running:\s*(\d+)$/); if (containersMatch && currentProject) { currentContainers = parseInt(containersMatch[1]); // Add the environment when we have complete information environments.push({ name: currentProject, path: currentPath, url: currentUrl, network: currentNetwork, containers: currentContainers, raw: line, }); // Reset for next project currentProject = null; currentPath = null; currentUrl = null; currentNetwork = null; currentContainers = null; continue; } // Stop parsing when we hit the services section if (cleanLine.includes("NAME") && cleanLine.includes("STATE")) { break; } } return environments; }