Skip to content

feat: refactor SSE transport for multiple connections and add prepare script #69

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

lmquang
Copy link

@lmquang lmquang commented Apr 5, 2025

This PR introduces two key improvements to the mcp-framework:

  1. Multiple SSE Connection Support:

    • Refactors the SSEServerTransport (src/transports/sse/server.ts) to handle multiple simultaneous client connections, removing the previous limitation of only supporting a single connection at a time.
    • Each connecting client is now assigned a unique connectionId.
    • The POST message endpoint now requires this connectionId (passed as the sessionId query parameter) to validate the request against an active connection.
    • Broadcasting messages via send() now correctly iterates over all active connections.
    • Keep-alive pings and connection cleanup logic have been updated to operate on a per-connection basis.
  2. Add prepare Script for Git Installs:

    • Adds a prepare script (npm run build) to package.json.
    • This ensures that the package is automatically compiled (tsc) when installed directly from a Git repository (e.g., using a GitHub URL in dependencies). This resolves issues where consuming projects would fail to build due to missing compiled files (dist folder) or type declarations.

These changes enhance the robustness and usability of the SSE transport, particularly for scenarios involving multiple clients, and improve the developer experience when using the framework directly from Git.

@lmquang
Copy link
Author

lmquang commented Apr 5, 2025

Hi there, I’d like to enhance the SSE transport feature. Currently, it throws a 409 error when more than one client connects to the server simultaneously. Could you please review this and let me know if there’s anything I can do to improve it? I’m open to making updates as needed.

@QuantGeekDev
Copy link
Owner

@lmquang Hey, thanks for your PR. I appreciate it a lot. This is awesome stuff. Could you help me come up with a testing plan for this? I want to make sure it's robust - do you mind walking me through how you tested this? No worries if not, I can test this independently too but it would help me review this faster. Does the 409 error on multiple client connection resolve when applying your code?

@lmquang
Copy link
Author

lmquang commented Apr 6, 2025

@QuantGeekDev

Here is a test scenario to compare before and after the SSE improvement

Both old and new version will use the same configuration:

    // --- Configure Transport ---
    let transportConfig: any;
    const port = args['--port'] || 3001;
    const host = args['--host'] || '0.0.0.0';

    if (args['--transport'] === 'sse') {
      logger.info(`\nConfiguring server for SSE transport on ${host}:${port}...`);

      transportConfig = {
        type: "sse", // Based on example
        options: {
          port: port,
          host: host,
          // Add other relevant options from example if needed (cors, auth, etc.)
          cors: { // Basic CORS for broad compatibility
            allowOrigin: "*",
            allowMethods: "GET, POST, DELETE, OPTIONS",
            allowHeaders: "Content-Type, Accept, Authorization, x-api-key, Mcp-Session-Id, Last-Event-ID",
            exposeHeaders: "Content-Type, Authorization, x-api-key, Mcp-Session-Id",
            maxAge: "86400"
          }
        }
      };
    }

Root Cause

The server uses the initial sessionId from the SSEServerTransport constructor to apply for all clients connecting to the server. Consequently, from the second client onwards, the server throws a 409 error in the handlePostMessage method because all clients share the same this._sessionId.

Test Scenario

The following recording (using mcp-framework v0.2.11) illustrates the issue:

  1. Run the MCP server with SSE transport.
  2. Client 1 (mcp inspector) connects to the server, and the server creates the initial $this_sessionId for Client 1. Client 1 uses resources and tools from the server as usual and maintains the connection.
  3. At this point, Client 2 (Mastra client) connects to the server, and Client 2 receives a 409 error because the server is using the same $this_sessionId for Client 2.
mcp-framework-v0_2_11.mp4

Test Scenario (with fix)

The following recording (using my modifications) demonstrates the fix:

  1. Run the MCP server with SSE transport.
  2. Client 1 (mcp inspector) connects to the server, and the server creates a unique connectionId for Client 1 and stores it in the connectionId Map. Client 1 uses resources and tools from the server as usual and maintains the connection.
  3. At this point, Client 2 (Mastra client) connects to the server, and Client 2 receives a new sessionId, and server stores it in the connectionId Map. Client 2 can now use resources and tools from the server as usual.
  4. Another client (Claude Desktop) connect to the server to test SSE connection.
mcp-framework-improvement.mp4

Note

To avoid confusion with the sessionId in the MCP framework, I’ve replaced it with connectionId. The connectionId is a unique identifier for each client connection, while the sessionId is a unique identifier for the MCP server. This change could be beneficial for future scalability features.

@lmquang
Copy link
Author

lmquang commented Apr 6, 2025

I apologize for the poor recording quality, as the GitHub file size is only 10 MB.

@QuantGeekDev
Copy link
Owner

This is a very smart way to approach it, thanks for the details. I will review again with more time tomorrow and merge. Thanks. Are you on our discord server?

@lmquang
Copy link
Author

lmquang commented Apr 8, 2025

thank you @QuantGeekDev , could you send me link to your discord server?

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.

2 participants