Restore negotiated protocol version on reconnection transport (#1591)

Co-authored-by: Matt <77928207+mattzcarey@users.noreply.github.com>
Co-authored-by: Felix Weinberger <3823880+felixweinberger@users.noreply.github.com>
This commit is contained in:
bhosmer-ant 2026-03-23 10:58:13 -04:00 • committed by GitHub
commit 72fe68b266
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -122,6 +122,58 @@ test('should initialize with supported older protocol version', async () => {
expect(client.getInstructions()).toBeUndefined();
});
/***
* Test: Reconnecting with the same Client restores protocol version on new transport
*/
test('should restore negotiated protocol version on transport when reconnecting with same client', async () => {
const setProtocolVersion = vi.fn();
const initialTransport: Transport = {
start: vi.fn().mockResolvedValue(undefined),
close: vi.fn().mockResolvedValue(undefined),
setProtocolVersion,
send: vi.fn().mockImplementation(message => {
if (message.method === 'initialize') {
initialTransport.onmessage?.({
jsonrpc: '2.0',
id: message.id,
result: {
protocolVersion: LATEST_PROTOCOL_VERSION,
capabilities: {},
serverInfo: { name: 'test', version: '1.0' }
}
});
}
return Promise.resolve();
})
};
const client = new Client({ name: 'test client', version: '1.0' });
await client.connect(initialTransport);
// Initial handshake should have set the protocol version on the transport
expect(setProtocolVersion).toHaveBeenCalledWith(LATEST_PROTOCOL_VERSION);
expect(client.getNegotiatedProtocolVersion()).toBe(LATEST_PROTOCOL_VERSION);
// Now simulate reconnection: new transport with a pre-existing sessionId.
// connect() will early-return without re-initializing, but MUST restore the protocol version
// so HTTP transports can keep sending the required mcp-protocol-version header.
const reconnectSetProtocolVersion = vi.fn();
const reconnectTransport: Transport = {
start: vi.fn().mockResolvedValue(undefined),
close: vi.fn().mockResolvedValue(undefined),
setProtocolVersion: reconnectSetProtocolVersion,
send: vi.fn().mockResolvedValue(undefined),
sessionId: 'existing-session-id'
};
await client.connect(reconnectTransport);
// No initialize request should have been sent (sessionId was set)
expect(reconnectTransport.send).not.toHaveBeenCalledWith(expect.objectContaining({ method: 'initialize' }), expect.anything());
// But the protocol version MUST have been restored onto the new transport
expect(reconnectSetProtocolVersion).toHaveBeenCalledWith(LATEST_PROTOCOL_VERSION);
});
/***
* Test: Reject Unsupported Protocol Version
*/