coding-tool-x 3.5.3 → 3.5.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -204,6 +204,8 @@ class McpClient extends EventEmitter {
204
204
  // HTTP/SSE transport state
205
205
  this._sseAbortController = null;
206
206
  this._httpSessionUrl = null;
207
+ this._httpSessionId = null;
208
+ this._negotiatedProtocolVersion = MCP_PROTOCOL_VERSION;
207
209
  }
208
210
 
209
211
  // --------------------------------------------------------------------------
@@ -249,11 +251,12 @@ class McpClient extends EventEmitter {
249
251
  }
250
252
  });
251
253
 
254
+ this._negotiatedProtocolVersion = result.protocolVersion || MCP_PROTOCOL_VERSION;
252
255
  this._serverCapabilities = result.capabilities || {};
253
256
  this._serverInfo = result.serverInfo || {};
254
257
 
255
258
  // Send initialized notification (no response expected)
256
- this._notify('notifications/initialized', {});
259
+ await this._notify('notifications/initialized', {});
257
260
 
258
261
  this._initialized = true;
259
262
  this.emit('initialized', result);
@@ -654,11 +657,18 @@ class McpClient extends EventEmitter {
654
657
  'Content-Type': 'application/json',
655
658
  'Content-Length': Buffer.byteLength(body),
656
659
  'Accept': 'application/json, text/event-stream',
660
+ ...(msg.method !== 'initialize'
661
+ ? {
662
+ 'MCP-Protocol-Version': this._negotiatedProtocolVersion || MCP_PROTOCOL_VERSION,
663
+ ...(this._httpSessionId ? { 'Mcp-Session-Id': this._httpSessionId } : {})
664
+ }
665
+ : {}),
657
666
  ...this._spec.headers
658
667
  }
659
668
  };
660
669
 
661
670
  const req = client.request(options, (res) => {
671
+ this._captureHttpResponseMetadata(res);
662
672
  let data = '';
663
673
  res.on('data', (chunk) => { data += chunk.toString(); });
664
674
  res.on('end', () => {
@@ -669,7 +679,19 @@ class McpClient extends EventEmitter {
669
679
  return;
670
680
  }
671
681
 
682
+ const isNotification = msg.id === undefined || msg.id === null;
672
683
  const contentType = res.headers['content-type'] || '';
684
+ const trimmedData = data.trim();
685
+
686
+ if (!trimmedData) {
687
+ if (isNotification || res.statusCode === 202 || res.statusCode === 204) {
688
+ resolve();
689
+ return;
690
+ }
691
+
692
+ reject(new McpClientError('Empty HTTP response for request'));
693
+ return;
694
+ }
673
695
 
674
696
  // JSON response (direct response to JSON-RPC)
675
697
  if (contentType.includes('application/json')) {
@@ -690,12 +712,6 @@ class McpClient extends EventEmitter {
690
712
  return;
691
713
  }
692
714
 
693
- // Accepted with no body (202, notifications)
694
- if (res.statusCode === 202 || !data.trim()) {
695
- resolve();
696
- return;
697
- }
698
-
699
715
  // Try parsing as JSON anyway
700
716
  try {
701
717
  const parsed = JSON.parse(data);
@@ -761,6 +777,8 @@ class McpClient extends EventEmitter {
761
777
  /** @private */
762
778
  _disconnectHttp() {
763
779
  this._httpSessionUrl = null;
780
+ this._httpSessionId = null;
781
+ this._negotiatedProtocolVersion = MCP_PROTOCOL_VERSION;
764
782
  }
765
783
 
766
784
  // --------------------------------------------------------------------------
@@ -807,7 +825,7 @@ class McpClient extends EventEmitter {
807
825
  }
808
826
 
809
827
  /** @private */
810
- _notify(method, params) {
828
+ async _notify(method, params) {
811
829
  const msg = {
812
830
  jsonrpc: JSONRPC_VERSION,
813
831
  method,
@@ -817,14 +835,20 @@ class McpClient extends EventEmitter {
817
835
  try {
818
836
  if (this._type === 'stdio') {
819
837
  this._sendStdio(msg);
838
+ return;
820
839
  } else {
821
- // Fire-and-forget for HTTP notifications
822
- this._sendHttp(msg).catch((err) => {
823
- this.emit('error', new McpClientError(`Notification send failed: ${err.message}`));
824
- });
840
+ await this._sendHttp(msg);
825
841
  }
826
842
  } catch (err) {
827
- this.emit('error', new McpClientError(`Notification send failed: ${err.message}`));
843
+ throw new McpClientError(`Notification send failed: ${err.message}`);
844
+ }
845
+ }
846
+
847
+ /** @private */
848
+ _captureHttpResponseMetadata(res) {
849
+ const sessionId = res && res.headers ? res.headers['mcp-session-id'] : null;
850
+ if (typeof sessionId === 'string' && sessionId.trim()) {
851
+ this._httpSessionId = sessionId.trim();
828
852
  }
829
853
  }
830
854