Skip to content

Commit 9b95a08

Browse files
author
Lasim
committed
feat(satellite): enhance MCP protocol to handle initialized notifications
1 parent 227294e commit 9b95a08

File tree

3 files changed

+43
-28
lines changed

3 files changed

+43
-28
lines changed

services/satellite/src/core/streamable-http-handler.ts

Lines changed: 30 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -309,35 +309,14 @@ export class StreamableHTTPHandler {
309309
// Set session ID header in response
310310
reply.header('Mcp-Session-Id', actualSessionId);
311311

312-
// Determine response mode
313-
const wantsStreaming = acceptHeader.includes('text/event-stream');
312+
// ALWAYS return JSON for initialize, even if Accept includes text/event-stream
313+
// The SSE stream is established via separate GET request
314+
reply.code(200).send(initResponse);
314315

315-
if (wantsStreaming) {
316-
// Return SSE stream
317-
reply.raw.writeHead(200, {
318-
'Content-Type': 'text/event-stream',
319-
'Cache-Control': 'no-cache',
320-
'Connection': 'keep-alive',
321-
'Mcp-Session-Id': actualSessionId
322-
});
323-
324-
const eventId = this.generateEventId();
325-
reply.raw.write(`id: ${eventId}\nevent: message\ndata: ${JSON.stringify(initResponse)}\n\n`);
326-
327-
this.logger.debug({
328-
operation: 'mcp_initialize_sse_response_sent',
329-
sessionId: actualSessionId,
330-
eventId
331-
}, 'Initialize SSE response sent');
332-
} else {
333-
// Return standard JSON response
334-
reply.code(200).send(initResponse);
335-
336-
this.logger.debug({
337-
operation: 'mcp_initialize_json_response_sent',
338-
sessionId: actualSessionId
339-
}, 'Initialize JSON response sent');
340-
}
316+
this.logger.debug({
317+
operation: 'mcp_initialize_json_response_sent',
318+
sessionId: actualSessionId
319+
}, 'Initialize JSON response sent');
341320
}
342321

343322
/**
@@ -383,6 +362,17 @@ export class StreamableHTTPHandler {
383362
// Process the message using the MCP protocol handler
384363
const response = await mcpProtocolHandler.handleMcpRequest(message, sessionId);
385364

365+
// Handle notifications (null response)
366+
if (response === null) {
367+
this.logger.debug({
368+
operation: 'mcp_notification_handled',
369+
sessionId,
370+
method: message.method
371+
}, 'MCP notification handled - no response sent');
372+
// Don't send anything for notifications
373+
return;
374+
}
375+
386376
this.logger.debug({
387377
operation: 'mcp_streaming_response_before_send',
388378
sessionId,
@@ -461,6 +451,18 @@ export class StreamableHTTPHandler {
461451
// Process the message using the MCP protocol handler
462452
const response = await mcpProtocolHandler.handleMcpRequest(message, sessionId);
463453

454+
// Handle notifications (null response)
455+
if (response === null) {
456+
this.logger.debug({
457+
operation: 'mcp_notification_handled',
458+
sessionId,
459+
method: message.method
460+
}, 'MCP notification handled - no response sent');
461+
// Don't send anything for notifications
462+
reply.code(204).send(); // 204 No Content
463+
return;
464+
}
465+
464466
this.logger.debug({
465467
operation: 'mcp_response_before_send',
466468
sessionId,

services/satellite/src/server.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,9 @@ export async function createServer() {
247247
runtimeState.listenToProcessManager(processManager);
248248

249249
// Initialize Remote Tool Discovery Manager for HTTP/SSE remote servers (EventBus will be added after registration)
250+
// NOTE: Do NOT call initialize() here - it will be called automatically after initial config is fetched
251+
// The RemoteToolDiscoveryManager has smart fallback: handleConfigurationUpdate() will trigger
252+
// full initialization if not yet initialized (see line 423-429 in remote-tool-discovery-manager.ts)
250253
const remoteToolDiscoveryManager = new RemoteToolDiscoveryManager(server.log);
251254
remoteToolDiscoveryManager.setConfigManager(dynamicConfigManager);
252255

services/satellite/src/services/mcp-protocol-handler.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,14 @@ export class McpProtocolHandler {
4848
result = await this.handleInitialize(params);
4949
break;
5050

51+
case 'notifications/initialized':
52+
// MCP notification - no response needed, just log and return null
53+
this.logger.debug({
54+
operation: 'mcp_notification_initialized',
55+
session_id: sessionId
56+
}, 'MCP client sent initialized notification');
57+
return null; // Notifications don't get responses
58+
5159
case 'tools/list':
5260
result = await this.handleToolsList();
5361
break;
@@ -440,6 +448,7 @@ export class McpProtocolHandler {
440448
isSupportedMethod(method: string): boolean {
441449
const supportedMethods = [
442450
'initialize',
451+
'notifications/initialized',
443452
'tools/list',
444453
'tools/call',
445454
'resources/list',
@@ -459,6 +468,7 @@ export class McpProtocolHandler {
459468
return {
460469
supported_methods: [
461470
'initialize',
471+
'notifications/initialized',
462472
'tools/list',
463473
'tools/call',
464474
'resources/list',

0 commit comments

Comments
 (0)