@sigyl-dev/cli
Version:
Official Sigyl CLI for installing and managing MCP packages. Zero-config installation for public packages, secure API-based authentication.
142 lines ⢠6.59 kB
JavaScript
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.dev = dev;
const chalk_1 = __importDefault(require("chalk"));
const node_path_1 = require("node:path");
const node_child_process_1 = require("node:child_process");
const node_fs_1 = require("node:fs");
const logger_1 = require("../logger");
const subprocess_1 = require("../lib/subprocess");
const inspector_1 = require("../lib/inspector");
const express_scanner_1 = require("../lib/express-scanner");
const mcp_generator_1 = require("../lib/mcp-generator");
async function dev(options) {
try {
const mcpPort = options.port || "8181";
const outDir = (0, node_path_1.join)(options.directory, "template-mcp");
let expressProcess;
let mcpProcess;
let isFirstBuild = true;
let isRebuilding = false;
console.log(chalk_1.default.blue("š Starting development mode..."));
// Function to rebuild MCP server from Express app
const rebuildMCPServer = async () => {
try {
(0, logger_1.verboseLog)("Scanning Express application...");
const scanner = new express_scanner_1.ExpressScanner(options.directory);
const endpoints = await scanner.scanForEndpoints();
if (endpoints.length > 0) {
(0, logger_1.verboseLog)(`Found ${endpoints.length} endpoints, generating MCP server...`);
const generator = new mcp_generator_1.MCPGenerator(outDir, options.serverLanguage || "typescript");
await generator.generateFromEndpoints(endpoints, {
appPort: options.appPort
});
(0, logger_1.verboseLog)("MCP server generated");
}
}
catch (error) {
console.error(chalk_1.default.red("ā Failed to rebuild MCP server:"), error);
}
};
// Function to start the Express app
const startExpressApp = async () => {
if (expressProcess && !expressProcess.killed) {
expressProcess.kill("SIGTERM");
await new Promise(resolve => setTimeout(resolve, 100));
}
// Try to detect and start Express app
const packageJsonPath = (0, node_path_1.join)(options.directory, "package.json");
if ((0, node_fs_1.existsSync)(packageJsonPath)) {
try {
const { process: expressProc, detectedPort } = await (0, subprocess_1.startSubprocess)("npm start", options.appPort, undefined, options.directory // Pass the directory to run the command in
);
expressProcess = expressProc;
options.appPort = detectedPort;
(0, logger_1.verboseLog)(`Express app started on port ${detectedPort}`);
}
catch (error) {
console.log(chalk_1.default.yellow("ā ļø Could not auto-start Express app"));
(0, logger_1.verboseLog)("You may need to start your Express app manually");
}
}
};
// Function to start MCP server
const startMCPServer = async () => {
if (mcpProcess && !mcpProcess.killed) {
isRebuilding = true;
mcpProcess.kill("SIGTERM");
await new Promise(resolve => setTimeout(resolve, 100));
}
const serverPath = (0, node_path_1.join)(outDir, "server.js");
if (!(0, node_fs_1.existsSync)(serverPath)) {
(0, logger_1.verboseLog)("MCP server not found, rebuilding...");
await rebuildMCPServer();
}
if ((0, node_fs_1.existsSync)(serverPath)) {
mcpProcess = (0, node_child_process_1.spawn)("node", [serverPath], {
stdio: ["inherit", "pipe", "pipe"],
env: {
...process.env,
PORT: mcpPort,
},
});
mcpProcess.stdout?.on("data", (data) => {
process.stdout.write(data);
});
mcpProcess.stderr?.on("data", (data) => {
process.stderr.write(data);
});
mcpProcess.on("exit", (code) => {
if (isRebuilding) {
isRebuilding = false;
return;
}
if (code !== 0 && code !== null) {
console.log(chalk_1.default.yellow(`ā ļø MCP server exited with code ${code}`));
}
});
if (isFirstBuild) {
console.log(chalk_1.default.green(`ā
MCP server starting on port ${mcpPort}`));
// Open MCP Inspector
if (options.open !== false) {
await (0, inspector_1.openMCPInspector)(mcpPort, options.inspectorUrl);
}
isFirstBuild = false;
}
}
};
// Initial setup
await startExpressApp();
await rebuildMCPServer();
await startMCPServer();
// TODO: Set up file watching for hot reload
// This would use chokidar or similar to watch for Express app changes
console.log(chalk_1.default.gray("Press Ctrl+C to stop the dev server"));
// Handle cleanup on exit
const cleanup = async () => {
console.log(chalk_1.default.yellow("\nš Shutting down dev server..."));
if (expressProcess && !expressProcess.killed) {
console.log(chalk_1.default.yellow("Stopping Express app..."));
expressProcess.kill("SIGTERM");
}
if (mcpProcess && !mcpProcess.killed) {
console.log(chalk_1.default.yellow("Stopping MCP server..."));
mcpProcess.kill("SIGTERM");
}
process.exit(0);
};
// Set up signal handlers
process.on("SIGINT", cleanup);
process.on("SIGTERM", cleanup);
// Keep the process alive
await new Promise(() => { });
}
catch (error) {
console.error(chalk_1.default.red("ā Dev server failed:"), error);
process.exit(1);
}
}
//# sourceMappingURL=dev.js.map
;