UNPKG

orchestry-mcp

Version:

Orchestry MCP Server for multi-session task management

167 lines • 6.24 kB
#!/usr/bin/env node import { spawn, exec } from 'child_process'; import path from 'path'; import { fileURLToPath } from 'url'; import net from 'net'; const __dirname = path.dirname(fileURLToPath(import.meta.url)); // Check if port is available function checkPort(port) { return new Promise((resolve) => { const server = net.createServer(); server.once('error', () => resolve(false)); server.once('listening', () => { server.close(); resolve(true); }); server.listen(port); }); } // Kill process on port function killPort(port) { return new Promise((resolve) => { if (process.platform === 'darwin' || process.platform === 'linux') { exec(`lsof -ti :${port} | xargs kill -9 2>/dev/null || true`, () => resolve()); } else { resolve(); } }); } // Open browser function openBrowser(url) { const platform = process.platform; let command; if (platform === 'darwin') { command = `open ${url}`; } else if (platform === 'win32') { command = `start ${url}`; } else { command = `xdg-open ${url}`; } exec(command); } async function main() { console.error('šŸš€ Starting Orchestry with Web UI...'); const API_PORT = 7531; const WEB_PORT = 7530; // Clean up ports if needed const apiAvailable = await checkPort(API_PORT); const webAvailable = await checkPort(WEB_PORT); if (!apiAvailable) { console.error(`āš ļø Port ${API_PORT} in use, cleaning up...`); await killPort(API_PORT); await new Promise(r => setTimeout(r, 500)); } if (!webAvailable) { console.error(`āš ļø Port ${WEB_PORT} in use, cleaning up...`); await killPort(WEB_PORT); await new Promise(r => setTimeout(r, 500)); } // Start the unified server in a child process const serverPath = path.join(__dirname, 'unified-server.js'); const serverProcess = spawn('node', [serverPath], { stdio: ['ignore', 'pipe', 'pipe'], env: { ...process.env, API_PORT: String(API_PORT), WEB_PORT: String(WEB_PORT), RUN_MODE: 'web', NODE_ENV: 'development', LAUNCHED_BY_ORCHESTRY: 'true' }, detached: false }); // Forward server output serverProcess.stdout?.on('data', (data) => { console.error(data.toString().trim()); }); serverProcess.stderr?.on('data', (data) => { console.error(data.toString().trim()); }); // Wait for servers to be ready let apiReady = false; let webReady = false; const checkServers = async () => { for (let i = 0; i < 30; i++) { if (!apiReady) { apiReady = !(await checkPort(API_PORT)); } if (!webReady) { webReady = !(await checkPort(WEB_PORT)); } if (apiReady && webReady) { console.error('\nāœ… Orchestry is running:'); console.error(` - MCP Server: Active (stdio)`); console.error(` - Web UI: http://localhost:${WEB_PORT}`); console.error(` - API: http://localhost:${API_PORT}`); // Open browser openBrowser(`http://localhost:${WEB_PORT}`); // Now start the MCP server in stdio mode const { Server } = await import('@modelcontextprotocol/sdk/server/index.js'); const { StdioServerTransport } = await import('@modelcontextprotocol/sdk/server/stdio.js'); const { DatabaseManager } = await import('./database-manager.js'); const { OrchestryTools } = await import('./tools/index.js'); const { CallToolRequestSchema, ListToolsRequestSchema } = await import('@modelcontextprotocol/sdk/types.js'); const mcpServer = new Server({ name: 'orchestry', version: '1.0.0', }, { capabilities: { tools: {}, }, }); const dbManager = new DatabaseManager(); const tools = new OrchestryTools(dbManager, null); // Register MCP tools mcpServer.setRequestHandler(ListToolsRequestSchema, async () => ({ tools: tools.getToolDefinitions(), })); mcpServer.setRequestHandler(CallToolRequestSchema, async (request) => { const { name, arguments: args } = request.params; try { const result = await tools.executeTool(name, args); return { content: [ { type: 'text', text: JSON.stringify(result, null, 2), }, ], }; } catch (error) { return { content: [ { type: 'text', text: `Error: ${error instanceof Error ? error.message : 'Unknown error'}`, }, ], }; } }); // Connect stdio transport const transport = new StdioServerTransport(); await mcpServer.connect(transport); return; } await new Promise(r => setTimeout(r, 1000)); } console.error('āŒ Timeout waiting for servers to start'); process.exit(1); }; await checkServers(); // Handle shutdown process.on('SIGINT', () => { console.error('\nšŸ›‘ Shutting down Orchestry...'); serverProcess.kill(); process.exit(0); }); } main().catch(error => { console.error('Failed to start Orchestry:', error); process.exit(1); }); //# sourceMappingURL=launcher.js.map