Skip to content

Fix logger multi-session cross-talk in HTTP mode#31

Open
Claude wants to merge 5 commits into
mainfrom
claude/fix-logger-multi-session-issue
Open

Fix logger multi-session cross-talk in HTTP mode#31
Claude wants to merge 5 commits into
mainfrom
claude/fix-logger-multi-session-issue

Conversation

@Claude
Copy link
Copy Markdown
Contributor

@Claude Claude AI commented Feb 23, 2026

The singleton Logger service was overwriting its internal MCP server reference on each new HTTP session, causing all log notifications to route only to the most recently connected user.

Changes

  • Logger service: Changed from single mcpServer reference to Set<McpServer> to track multiple active sessions

    • setMcpServer() now adds servers to the Set instead of overwriting
    • Added removeMcpServer() to clean up closed sessions and prevent memory leaks
    • sendMcpLog() broadcasts to all registered servers using Promise.allSettled()
  • HTTP session handler: Call removeMcpServer() in the transport.onclose callback to remove terminated sessions from the logger's notification list

  • Tests: Added multi-session test coverage verifying notifications reach all active sessions and that removed sessions stop receiving logs

Example

// Before: Each session overwrote the previous
logger.setMcpServer(sessionServer1); // sessionServer1 receives logs
logger.setMcpServer(sessionServer2); // Only sessionServer2 receives logs now

// After: All sessions receive logs
logger.setMcpServer(sessionServer1);
logger.setMcpServer(sessionServer2); // Both receive logs
logger.removeMcpServer(sessionServer1); // Only sessionServer2 receives logs

Stdio transport mode continues working as before with a single server in the Set.

Original prompt

This section details on the original issue you should resolve

<issue_title>Logger Multi-Session Cross-Talk in HTTP Mode</issue_title>
<issue_description>Description: The singleton Logger service overwrites its internal MCP server reference every time a new HTTP session is created.

Impact: Log notifications from all active users are sent only to the most recently connected user.

Recommended Fix: Update the logger to be session-aware or maintain a list of active MCP servers to notify for multi-session HTTP deployments.

Affected Files: src/services/logger.service.ts, src/index.ts.</issue_description>

Comments on the Issue (you are @claude[agent] in this section)

- Changed Logger to maintain a Set of MCP servers instead of single reference
- Added removeMcpServer() method to clean up closed sessions
- Updated sendMcpLog() to notify all registered servers in parallel
- Updated HTTP session handler to call removeMcpServer() on close
- Added tests for multi-session logger behavior
- All 110 tests pass successfully

Co-authored-by: gkorland <753206+gkorland@users.noreply.github.com>
@Claude Claude AI changed the title [WIP] Fix logger multi-session cross-talk in HTTP mode Fix logger multi-session cross-talk in HTTP mode Feb 23, 2026
@Claude Claude AI requested a review from gkorland February 23, 2026 08:35
@gkorland gkorland marked this pull request as ready for review February 23, 2026 09:07
@codecov
Copy link
Copy Markdown

codecov Bot commented Feb 23, 2026

Codecov Report

❌ Patch coverage is 86.66667% with 2 lines in your changes missing coverage. Please review.
✅ Project coverage is 49.01%. Comparing base (2b24b1d) to head (ba9b8c3).

Files with missing lines Patch % Lines
src/index.ts 0.00% 2 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main      #31      +/-   ##
==========================================
+ Coverage   48.32%   49.01%   +0.68%     
==========================================
  Files          11       11              
  Lines         449      457       +8     
  Branches      103      103              
==========================================
+ Hits          217      224       +7     
- Misses        232      233       +1     
Flag Coverage Δ
unittests 49.01% <86.66%> (+0.68%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes a critical bug where the singleton Logger service was overwriting its internal MCP server reference on each new HTTP session, causing log notifications from all active users to be sent only to the most recently connected user. The solution changes the Logger from tracking a single mcpServer to maintaining a Set<McpServer> to support multiple concurrent HTTP sessions.

Changes:

  • Refactored Logger service to use Set<McpServer> instead of a single server reference, enabling multi-session logging in HTTP mode
  • Added removeMcpServer() method and updated session cleanup to prevent memory leaks when sessions close
  • Added comprehensive test coverage for multi-session scenarios and server removal

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

File Description
src/services/logger.service.ts Changed from single mcpServer field to Set<McpServer>, updated setMcpServer() to add to Set, added removeMcpServer() for cleanup, and modified sendMcpLog() to broadcast to all registered servers using Promise.allSettled()
src/index.ts Moved sessionServer declaration before transport.onclose callback (to capture in closure) and added logger.removeMcpServer(sessionServer) call in the close handler to clean up terminated sessions
src/services/logger.service.test.ts Added tests for multiple server support and server removal functionality to verify notifications reach all active sessions and removed sessions stop receiving logs

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +116 to +169
it('should support multiple MCP servers for multi-session deployments', async () => {
const mockServer1 = {
server: {
notification: jest.fn().mockResolvedValue(undefined),
},
};
const mockServer2 = {
server: {
notification: jest.fn().mockResolvedValue(undefined),
},
};

// Add both servers
logger.setMcpServer(mockServer1 as any);
logger.setMcpServer(mockServer2 as any);

// Log a message
await logger.info('Test message for multiple servers');

// Both servers should receive the notification
expect(mockServer1.server.notification).toHaveBeenCalled();
expect(mockServer2.server.notification).toHaveBeenCalled();
});

it('should remove MCP server from notification list', async () => {
const mockServer1 = {
server: {
notification: jest.fn().mockResolvedValue(undefined),
},
};
const mockServer2 = {
server: {
notification: jest.fn().mockResolvedValue(undefined),
},
};

// Add both servers
logger.setMcpServer(mockServer1 as any);
logger.setMcpServer(mockServer2 as any);

// Remove server1
logger.removeMcpServer(mockServer1 as any);

// Clear previous calls
mockServer1.server.notification.mockClear();
mockServer2.server.notification.mockClear();

// Log a message
await logger.info('Test message after removing server');

// Only server2 should receive the notification
expect(mockServer1.server.notification).not.toHaveBeenCalled();
expect(mockServer2.server.notification).toHaveBeenCalled();
});
Copy link

Copilot AI Feb 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The tests are adding mock servers to the singleton logger instance without cleaning them up afterward. While this doesn't cause issues with the current test order, it could lead to test pollution if new tests are added later.

Consider adding cleanup in the afterEach hook to reset the logger's server list. This would make tests more isolated and maintainable. For example:

afterEach(() => {
  // Clear all registered servers to prevent test pollution
  // This assumes we add a method like clearServers() or expose mcpServers for testing
  consoleErrorSpy.mockRestore();
});

Note: This would require either adding a test-only method to clear servers or making the mcpServers property accessible for testing purposes.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Logger Multi-Session Cross-Talk in HTTP Mode

4 participants