Skip to content

Latest commit

 

History

History
226 lines (168 loc) · 6.95 KB

File metadata and controls

226 lines (168 loc) · 6.95 KB

MCP Server Notification Handler Fix

Issue Summary

The MCP server was failing to connect with VS Code and other MCP clients with the following error:

Error 500 status sending message to http://localhost:3456/mcp:
{"jsonrpc":"2.0","error":{"code":-32601,"message":"Internal server error",
"data":"MCP error -32601: Method 'notifications/initialized' not found"},"id":null}

Root Cause

The server implementation was missing proper handlers for MCP protocol notifications:

  1. No notifications/initialized handler
  2. JSON-RPC message processing didn't distinguish between notifications and requests
  3. HTTP response handling didn't account for notification-specific behavior

Per the JSON-RPC 2.0 specification:

  • Notifications don't have an id field and expect no response
  • Requests have an id field and expect a response with the same id

Solution Implemented

1. Added Notification Handler Registration (index.ts:1103-1124)

Created setupNotificationHandlers() method to register MCP protocol notifications:

private setupNotificationHandlers() {
  // Initialize notification handlers map
  this.server['_notificationHandlers'] = this.server['_notificationHandlers'] || new Map();

  // Handle notifications/initialized - sent by MCP clients after connection
  this.server['_notificationHandlers'].set('notifications/initialized', async (notification: any) => {
    this.log('info', 'MCP client initialized successfully');
    // No response needed for notifications per JSON-RPC 2.0 spec
  });

  // Handle notifications/cancelled - sent when client cancels an operation
  this.server['_notificationHandlers'].set('notifications/cancelled', async (notification: any) => {
    this.log('info', 'Client cancelled operation', notification.params);
  });

  // Handle notifications/progress - progress updates from client
  this.server['_notificationHandlers'].set('notifications/progress', async (notification: any) => {
    this.log('debug', 'Progress notification received', notification.params);
  });
}

2. Updated Constructor (index.ts:56)

Added call to setupNotificationHandlers() in constructor after other handler setups:

constructor() {
  // ... existing code ...
  this.setupToolHandlers();
  this.setupResourceHandlers();
  this.setupPromptHandlers();
  this.setupNotificationHandlers(); // NEW
  this.server.onerror = (error: any) => this.log('error', `Server error: ${error.message || error}`);
}

3. Enhanced JSON-RPC Message Handler (index.ts:1246-1294)

Modified handleJsonRpcMessage() to distinguish between notifications and requests:

private async handleJsonRpcMessage(request: any): Promise<any> {
  const { method, id } = request;

  // Per JSON-RPC 2.0 spec: notifications don't have an 'id' field
  const isNotification = id === undefined || id === null;

  if (isNotification) {
    // Handle notification - no response expected
    const notificationHandler = this.server['_notificationHandlers']?.get(method);

    if (!notificationHandler) {
      // Per JSON-RPC 2.0: no error response for notifications with unknown methods
      this.log('warn', `Notification handler not found for method '${method}', ignoring`);
      return null;
    }

    await notificationHandler(request);
    return null; // No response for notifications

  } else {
    // Handle request - response expected
    const handler = this.server['_requestHandlers'].get(method);

    if (!handler) {
      throw new McpError(ErrorCode.MethodNotFound, `Method '${method}' not found`);
    }

    const result = await handler(request);
    return { jsonrpc: '2.0', result, id };
  }
}

4. Updated HTTP Endpoint (index.ts:1187-1225)

Modified HTTP /mcp endpoint to return proper status codes:

app.post('/mcp', (req: Request, res: Response) => {
  this.handleJsonRpcMessage(req.body).then(result => {
    // Per JSON-RPC 2.0 spec: notifications return null and should get 204 No Content
    if (result === null) {
      this.log('debug', 'Notification processed, sending 204 No Content');
      res.status(204).end();
    } else {
      this.log('debug', 'Sending MCP response', result);
      res.json(result);
    }
  }).catch((error: Error) => {
    // ... error handling ...
  });
});

Testing Results

Created comprehensive test script (test-notification.js) to verify the fix:

Test Results ✅

Test 1: Sending notification/initialized
  Status Code: 204 No Content
  ✅ PASS

Test 2: Sending tools/list request (regular request)
  Status Code: 200 with JSON response
  ✅ PASS

Test 3: Sending notification/cancelled
  Status Code: 204 No Content
  ✅ PASS

Test 4: Health check
  Status Code: 200
  ✅ PASS

Server Logs Verification

Server correctly logged notification processing:

2025-11-04T23:47:00.766Z [n8n-workflow-builder] [info] MCP client initialized successfully
2025-11-04T23:47:00.770Z [n8n-workflow-builder] [info] Client cancelled operation { requestId: 123 }

Key Changes Summary

Component Change File Location
Notification Handlers Added registration method index.ts:1103-1124
Constructor Added handler initialization call index.ts:56
Message Processing Added notification vs. request logic index.ts:1246-1294
HTTP Endpoint Added 204 response for notifications index.ts:1187-1225

JSON-RPC 2.0 Compliance

The fix ensures proper compliance with JSON-RPC 2.0 specification:

  1. Notifications (no id field):

    • No response sent to client
    • HTTP 204 No Content status code
    • Errors logged but not returned
  2. Requests (with id field):

    • Response with matching id field
    • HTTP 200 OK with JSON body
    • Errors returned as JSON-RPC error responses

Impact

  • Severity: High (blocking MCP client integration)
  • Fix Status: ✅ Completed and tested
  • Breaking Changes: None (backward compatible)
  • Build Status: ✅ TypeScript compilation successful

Files Modified

  1. src/index.ts - Added notification support
  2. test-notification.js - Created test script (new file)
  3. NOTIFICATION_FIX_SUMMARY.md - This documentation (new file)

How to Test

  1. Build the project:

    npm run build
  2. Start server in standalone mode:

    MCP_STANDALONE=true npm start
  3. Run test script:

    node test-notification.js
  4. Expected output: All tests pass with ✅ checkmarks

Next Steps

  • ✅ MCP clients (VS Code, Claude Desktop) can now connect successfully
  • ✅ Server properly handles notifications/initialized on connection
  • ✅ Server properly handles notifications/cancelled for operation cancellation
  • ✅ Server properly handles notifications/progress for progress updates

References