@hivetechs/hive-ai
Version:
Real-time streaming AI consensus platform with HTTP+SSE MCP integration for Claude Code, VS Code, Cursor, and Windsurf - powered by OpenRouter's unified API
159 lines • 5.91 kB
JavaScript
/**
* Stdio Bridge MCP Server
*
* Bridges between Claude Code's stdio transport and our HTTP+SSE streaming server.
* This allows Claude Code to launch via command while maintaining streaming capabilities.
*/
export class StdioBridgeMCPServer {
httpServerProcess = null;
httpServerPort = 3000;
async start() {
// Start the HTTP+SSE server in background
await this.startHttpServer();
// Handle stdio communication
this.handleStdioMessages();
}
async startHttpServer() {
const { MCPPortManager } = await import('../tools/mcp-port-manager.js');
const portManager = new MCPPortManager();
const { port } = await portManager.getBestPort();
this.httpServerPort = port;
// Start HTTP server directly (not via command to avoid recursion)
const { HiveAIMCPServer } = await import('./server.js');
const httpServer = new HiveAIMCPServer(port);
// Start in background
httpServer.start().catch(console.error);
// Wait for server to be ready
await new Promise(resolve => setTimeout(resolve, 3000));
}
handleStdioMessages() {
process.stdin.setEncoding('utf8');
let buffer = '';
process.stdin.on('data', async (chunk) => {
buffer += chunk;
// Process complete JSON-RPC messages
const lines = buffer.split('\n');
buffer = lines.pop() || '';
for (const line of lines) {
if (line.trim()) {
try {
const request = JSON.parse(line);
const response = await this.handleRequest(request);
this.sendResponse(response);
}
catch (error) {
this.sendError(null, -32700, 'Parse error');
}
}
}
});
process.stdin.on('end', () => {
this.cleanup();
});
}
async handleRequest(request) {
try {
switch (request.method) {
case 'initialize':
return {
jsonrpc: '2.0',
id: request.id,
result: {
protocolVersion: '2025-03-26',
capabilities: {
tools: { listChanged: true },
resources: {},
prompts: {},
logging: {}
},
serverInfo: {
name: 'hive-ai-bridge',
version: await import('../utils/version-utils.js').then(m => m.getCurrentVersion())
}
}
};
case 'tools/list':
return {
jsonrpc: '2.0',
id: request.id,
result: {
tools: [
{
name: 'hive_consensus',
description: 'Run 4-stage AI consensus with real-time streaming',
inputSchema: {
type: 'object',
properties: {
question: { type: 'string', description: 'The question for consensus analysis' }
},
required: ['question']
}
}
]
}
};
case 'tools/call':
// Bridge tool calls to HTTP server
return await this.bridgeToolCall(request);
default:
return {
jsonrpc: '2.0',
id: request.id,
error: { code: -32601, message: 'Method not found' }
};
}
}
catch (error) {
return {
jsonrpc: '2.0',
id: request.id,
error: { code: -32000, message: `Internal error: ${error}` }
};
}
}
async bridgeToolCall(request) {
try {
// Make HTTP request to our streaming server
const response = await fetch(`http://localhost:${this.httpServerPort}/mcp`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(request)
});
if (response.ok) {
const result = await response.json();
return result;
}
else {
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
}
}
catch (error) {
return {
jsonrpc: '2.0',
id: request.id,
error: { code: -32000, message: `Bridge error: ${error}` }
};
}
}
sendResponse(response) {
process.stdout.write(JSON.stringify(response) + '\n');
}
sendError(id, code, message) {
const errorResponse = {
jsonrpc: '2.0',
id,
error: { code, message }
};
this.sendResponse(errorResponse);
}
cleanup() {
if (this.httpServerProcess) {
this.httpServerProcess.kill();
}
}
}
export async function startStdioBridgeServer() {
const server = new StdioBridgeMCPServer();
await server.start();
}
//# sourceMappingURL=stdio-bridge-server.js.map