Skip to content

Hook Handlers Being Overwritten in McpServer and Server #322

@nichtsam

Description

@nichtsam

Describe the bug

When using McpServer or Server, any previously assigned onclose, onmessage, and onerror handlers get overwritten by the underlying Protocol.connect. This behavior prevents attaching custom logic (e.g., cleanup tasks on onclose) outside of the protocol, as those handlers will be silently lost.

You can see the code here:
https://github.com/modelcontextprotocol/typescript-sdk/blob/main/src/shared/protocol.ts#L267-L287

This design makes the Transport interface harder to extend or compose with custom application-level logic.

To Reproduce

Steps to reproduce the behavior:

  1. Assign a custom onclose handler to a transport:
transport.onclose = () => {
  console.log('Cleanup logic called');
};
  1. Pass the transport into Protocol.connect(transport)
  2. Close the connection
  3. The custom onclose handler will never be called.

Expected behavior

I expected Protocol to preserve or compose with the existing handlers (e.g. call them in addition), or for the Transport interface to support multiple listeners (e.g. addEventListener-style).

Alternatively, documentation should clearly mention that using Protocol takes exclusive ownership of the transport event handlers.

Additional context

This became an issue when I tried to delete the transport from a session map on onclose. However, the handler was silently overwritten by the protocol logic and was never triggered.

Since I was already using a custom Transport implementation to support Web API-style request/response, I just extended my custom class to handle additional headers and invoke them accordingly as a workaround.

For reference, here’s my use case:
https://github.com/nichtsam/nichtsam.com/blob/dev/app/routes/mcp%2B/mcp.server.ts

Thanks for the great library! I’d love to know if this behavior is by design, or if there’s potential for an enhancement.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions