@aiwerk/mcp-bridge 1.1.6 → 1.1.7

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.
@@ -22,8 +22,10 @@ export declare class StandaloneServer {
22
22
  private handleInitialize;
23
23
  private handleToolsList;
24
24
  private handleToolsCall;
25
+ private discoveryPromise?;
25
26
  /** Connect to all backend servers and discover their tools (direct mode). */
26
27
  private discoverDirectTools;
28
+ private _doDiscovery;
27
29
  private createTransport;
28
30
  /** Graceful shutdown: disconnect all backend servers. */
29
31
  shutdown(): Promise<void>;
@@ -245,10 +245,24 @@ export class StandaloneServer {
245
245
  };
246
246
  }
247
247
  }
248
+ discoveryPromise;
248
249
  /** Connect to all backend servers and discover their tools (direct mode). */
249
250
  async discoverDirectTools(force = false) {
250
251
  if (this.directTools.length > 0 && !force)
251
252
  return; // Already discovered
253
+ if (this.discoveryPromise && !force) {
254
+ await this.discoveryPromise;
255
+ return;
256
+ }
257
+ this.discoveryPromise = this._doDiscovery(force);
258
+ try {
259
+ await this.discoveryPromise;
260
+ }
261
+ finally {
262
+ this.discoveryPromise = undefined;
263
+ }
264
+ }
265
+ async _doDiscovery(force) {
252
266
  if (force) {
253
267
  this.directTools = [];
254
268
  for (const [, conn] of this.directConnections) {
@@ -57,17 +57,34 @@ export class StreamableHttpTransport extends BaseTransport {
57
57
  let jsonResponse;
58
58
  if (contentType.includes("text/event-stream")) {
59
59
  const text = await response.text();
60
- const dataLines = text.split('\n')
61
- .filter((line) => line.startsWith('data:'))
62
- .map((line) => line.substring(5).trim());
63
- if (dataLines.length === 0) {
64
- throw new Error("No data lines in SSE response");
65
- }
66
- for (const dl of dataLines) {
60
+ const lines = text.split('\n');
61
+ // SSE event boundary parsing: collect data lines, dispatch on empty line
62
+ let dataBuffer = [];
63
+ const dispatch = () => {
64
+ if (dataBuffer.length === 0)
65
+ return;
66
+ const data = dataBuffer.join("\n");
67
+ dataBuffer = [];
67
68
  try {
68
- this.handleMessage(JSON.parse(dl));
69
+ this.handleMessage(JSON.parse(data));
70
+ }
71
+ catch { /* skip malformed events */ }
72
+ };
73
+ let hasData = false;
74
+ for (const line of lines) {
75
+ const trimmed = line.trim();
76
+ if (trimmed.startsWith("data:")) {
77
+ dataBuffer.push(trimmed.substring(5).trimStart());
78
+ hasData = true;
69
79
  }
70
- catch { /* skip malformed lines */ }
80
+ else if (trimmed === "" && dataBuffer.length > 0) {
81
+ dispatch();
82
+ }
83
+ }
84
+ // Dispatch any trailing data (server may omit final empty line)
85
+ dispatch();
86
+ if (!hasData) {
87
+ throw new Error("No data lines in SSE response");
71
88
  }
72
89
  }
73
90
  else {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aiwerk/mcp-bridge",
3
- "version": "1.1.6",
3
+ "version": "1.1.7",
4
4
  "description": "Standalone MCP server that multiplexes multiple MCP servers into one interface",
5
5
  "type": "module",
6
6
  "main": "./dist/src/index.js",