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:
parent
0784be1a67
commit
72fe68b266
2 changed files with 103 additions and 1 deletions
|
|
@ -194,6 +194,7 @@ export type ClientOptions = ProtocolOptions & {
|
|||
export class Client extends Protocol<ClientContext> {
|
||||
private _serverCapabilities?: ServerCapabilities;
|
||||
private _serverVersion?: Implementation;
|
||||
private _negotiatedProtocolVersion?: string;
|
||||
private _capabilities: ClientCapabilities;
|
||||
private _instructions?: string;
|
||||
private _jsonSchemaValidator: jsonSchemaValidator;
|
||||
|
|
@ -470,8 +471,12 @@ export class Client extends Protocol<ClientContext> {
|
|||
override async connect(transport: Transport, options?: RequestOptions): Promise<void> {
|
||||
await super.connect(transport);
|
||||
// When transport sessionId is already set this means we are trying to reconnect.
|
||||
// In this case we don't need to initialize again.
|
||||
// Restore the protocol version negotiated during the original initialize handshake
|
||||
// so HTTP transports include the required mcp-protocol-version header, but skip re-init.
|
||||
if (transport.sessionId !== undefined) {
|
||||
if (this._negotiatedProtocolVersion !== undefined && transport.setProtocolVersion) {
|
||||
transport.setProtocolVersion(this._negotiatedProtocolVersion);
|
||||
}
|
||||
return;
|
||||
}
|
||||
try {
|
||||
|
|
@ -498,6 +503,7 @@ export class Client extends Protocol<ClientContext> {
|
|||
|
||||
this._serverCapabilities = result.capabilities;
|
||||
this._serverVersion = result.serverInfo;
|
||||
this._negotiatedProtocolVersion = result.protocolVersion;
|
||||
// HTTP transports must set the protocol version in each header after initialization.
|
||||
if (transport.setProtocolVersion) {
|
||||
transport.setProtocolVersion(result.protocolVersion);
|
||||
|
|
@ -535,6 +541,15 @@ export class Client extends Protocol<ClientContext> {
|
|||
return this._serverVersion;
|
||||
}
|
||||
|
||||
/**
|
||||
* After initialization has completed, this will be populated with the protocol version negotiated
|
||||
* during the initialize handshake. When manually reconstructing a transport for reconnection, pass this
|
||||
* value to the new transport so it continues sending the required `mcp-protocol-version` header.
|
||||
*/
|
||||
getNegotiatedProtocolVersion(): string | undefined {
|
||||
return this._negotiatedProtocolVersion;
|
||||
}
|
||||
|
||||
/**
|
||||
* After initialization has completed, this may be populated with information about the server's instructions.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -118,6 +118,13 @@ export type StreamableHTTPClientTransportOptions = {
|
|||
* When not provided and connecting to a server that supports session IDs, the server will generate a new session ID.
|
||||
*/
|
||||
sessionId?: string;
|
||||
|
||||
/**
|
||||
* The MCP protocol version to include in the `mcp-protocol-version` header on all requests.
|
||||
* When reconnecting with a preserved `sessionId`, set this to the version negotiated during the original
|
||||
* handshake so the reconnected transport continues sending the required header.
|
||||
*/
|
||||
protocolVersion?: string;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -155,6 +162,7 @@ export class StreamableHTTPClientTransport implements Transport {
|
|||
this._fetch = opts?.fetch;
|
||||
this._fetchWithInit = createFetchWithInit(opts?.fetch, opts?.requestInit);
|
||||
this._sessionId = opts?.sessionId;
|
||||
this._protocolVersion = opts?.protocolVersion;
|
||||
this._reconnectionOptions = opts?.reconnectionOptions ?? DEFAULT_STREAMABLE_HTTP_RECONNECTION_OPTIONS;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue