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