orchestry-mcp
Version:
Orchestry MCP Server for multi-session task management
167 lines ⢠6.24 kB
JavaScript
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