@@ -460,13 +460,15 @@ export class CudaQuantumHttpServer {
|
||||
});
|
||||
|
||||
// ===== MCP JSON-RPC Endpoints =====
|
||||
// Main MCP endpoint for JSON-RPC requests
|
||||
// Main MCP endpoint for JSON-RPC requests (root endpoint)
|
||||
this.app.post('/', this.handleMcpJsonRpc.bind(this));
|
||||
this.app.post('/mcp', this.handleMcpJsonRpc.bind(this));
|
||||
this.app.post('/mcp/v1', this.handleMcpJsonRpc.bind(this));
|
||||
|
||||
// MCP SSE endpoint for streaming
|
||||
this.app.get('/mcp/sse', this.handleMcpSSE.bind(this));
|
||||
// MCP SSE endpoint for streaming (separate endpoint)
|
||||
this.app.get('/sse', this.handleMcpSSE.bind(this));
|
||||
this.app.get('/mcp/sse', this.handleMcpSSE.bind(this));
|
||||
this.app.get('/events', this.handleMcpSSE.bind(this));
|
||||
|
||||
// ===== Legacy REST API Endpoints (for backward compatibility) =====
|
||||
// Quantum Kernels
|
||||
@@ -696,6 +698,8 @@ export class CudaQuantumHttpServer {
|
||||
private handleMcpSSE(req: Request, res: Response): void {
|
||||
const clientId = Math.random().toString(36).substring(2, 15);
|
||||
|
||||
this.logger.info(`MCP SSE client connecting: ${clientId}`);
|
||||
|
||||
// Setup SSE headers
|
||||
res.writeHead(200, {
|
||||
'Content-Type': 'text/event-stream',
|
||||
@@ -714,36 +718,53 @@ export class CudaQuantumHttpServer {
|
||||
|
||||
this.sseClients.set(clientId, client);
|
||||
|
||||
// Send initial connection event with MCP endpoint notification
|
||||
const initMessage = {
|
||||
type: 'endpoint',
|
||||
uri: `/mcp`,
|
||||
timestamp: new Date().toISOString()
|
||||
};
|
||||
res.write(`data: ${JSON.stringify(initMessage)}\n\n`);
|
||||
// Send initial endpoint event - this is critical for MCP handshake
|
||||
const protocol = req.protocol || 'https';
|
||||
const host = req.get('host') || 'localhost:3000';
|
||||
const baseUrl = `${protocol}://${host}`;
|
||||
|
||||
// Send keepalive every 30 seconds
|
||||
const endpointMessage = {
|
||||
jsonrpc: '2.0',
|
||||
method: 'endpoint',
|
||||
params: {
|
||||
uri: baseUrl
|
||||
}
|
||||
};
|
||||
|
||||
res.write(`event: endpoint\n`);
|
||||
res.write(`data: ${JSON.stringify(endpointMessage)}\n\n`);
|
||||
|
||||
this.logger.info(`Sent endpoint to client ${clientId}: ${baseUrl}`);
|
||||
|
||||
// Send keepalive every 15 seconds
|
||||
const keepaliveInterval = setInterval(() => {
|
||||
if (this.sseClients.has(clientId)) {
|
||||
try {
|
||||
res.write(`: keepalive\n\n`);
|
||||
} catch (error) {
|
||||
this.logger.warn(`Keepalive failed for client ${clientId}`);
|
||||
clearInterval(keepaliveInterval);
|
||||
this.sseClients.delete(clientId);
|
||||
}
|
||||
} else {
|
||||
clearInterval(keepaliveInterval);
|
||||
}
|
||||
}, 30000);
|
||||
}, 15000);
|
||||
|
||||
// Handle client disconnect
|
||||
req.on('close', () => {
|
||||
clearInterval(keepaliveInterval);
|
||||
this.sseClients.delete(clientId);
|
||||
this.logger.debug(`MCP SSE client ${clientId} disconnected`);
|
||||
this.logger.info(`MCP SSE client ${clientId} disconnected`);
|
||||
});
|
||||
|
||||
this.logger.debug(`MCP SSE client ${clientId} connected`);
|
||||
req.on('error', (error) => {
|
||||
this.logger.error(`MCP SSE client ${clientId} error:`, error);
|
||||
clearInterval(keepaliveInterval);
|
||||
this.sseClients.delete(clientId);
|
||||
});
|
||||
|
||||
this.logger.info(`MCP SSE client ${clientId} connected successfully`);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Referencia en una nueva incidencia
Block a user