@aiwerk/mcp-bridge 2.8.30 → 2.8.31

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.
@@ -14,6 +14,7 @@ export declare class StandaloneServer {
14
14
  private readonly requestIdState;
15
15
  private directTools;
16
16
  private directConnections;
17
+ private stdoutRef;
17
18
  constructor(config: BridgeConfig, logger: Logger);
18
19
  private isRouterMode;
19
20
  /** Start stdio mode: read JSON-RPC from stdin, write responses to stdout.
@@ -30,6 +31,8 @@ export declare class StandaloneServer {
30
31
  /** Connect to all backend servers and discover their tools (direct mode). */
31
32
  private discoverDirectTools;
32
33
  private _doDiscovery;
34
+ /** Send notifications/tools/list_changed to the client via stdout */
35
+ private sendToolsChanged;
33
36
  /** Extract server name from a tool name like "todoist_call" or "github_call" */
34
37
  private guessServerFromToolName;
35
38
  /** Discover tools from a single server (lazy, per-server) */
@@ -26,6 +26,7 @@ export class StandaloneServer {
26
26
  // Direct mode state
27
27
  directTools = [];
28
28
  directConnections = new Map();
29
+ stdoutRef = null;
29
30
  constructor(config, logger) {
30
31
  this.config = config;
31
32
  this.logger = logger;
@@ -50,6 +51,7 @@ export class StandaloneServer {
50
51
  async startStdio() {
51
52
  const stdin = process.stdin;
52
53
  const stdout = process.stdout;
54
+ this.stdoutRef = stdout;
53
55
  let buffer = Buffer.alloc(0);
54
56
  // LSP framing state
55
57
  let lspContentLength = -1; // -1 means not in LSP mode for current message
@@ -346,16 +348,20 @@ export class StandaloneServer {
346
348
  if (serverName) {
347
349
  this.logger.info(`[mcp-bridge] Lazy discovery for server: ${serverName} (triggered by ${toolName})`);
348
350
  await this.discoverSingleServer(serverName);
349
- // After discovery, the placeholder tool no longer exists - return discovered tools
350
- const serverTools = this.directTools.filter(t => t.serverName === serverName);
351
- const discovered = serverTools.map(t => `${t.registeredName}: ${t.description}`);
352
- return {
353
- jsonrpc: "2.0",
354
- id,
355
- result: {
356
- content: [{ type: "text", text: `Discovered ${serverTools.length} tools from ${serverName}. Available tools:\n\n${discovered.join("\n")}\n\nCall any of these tools directly by name.` }]
357
- }
358
- };
351
+ // After discovery, try to find the real tool
352
+ entry = this.directTools.find(t => t.registeredName === toolName);
353
+ if (!entry) {
354
+ // Placeholder was called — return discovered tools list and notify client to refresh
355
+ const serverTools = this.directTools.filter(t => t.serverName === serverName);
356
+ const discovered = serverTools.map(t => `${t.registeredName}: ${t.description}`);
357
+ return {
358
+ jsonrpc: "2.0",
359
+ id,
360
+ result: {
361
+ content: [{ type: "text", text: `Server "${serverName}" is now connected with ${serverTools.length} tools. The tool list has been updated — please retry your request. Available tools:\n\n${discovered.join("\n")}` }]
362
+ }
363
+ };
364
+ }
359
365
  }
360
366
  }
361
367
  if (!entry) {
@@ -494,6 +500,14 @@ export class StandaloneServer {
494
500
  }
495
501
  }
496
502
  }
503
+ /** Send notifications/tools/list_changed to the client via stdout */
504
+ sendToolsChanged() {
505
+ if (!this.stdoutRef)
506
+ return;
507
+ const notification = { jsonrpc: "2.0", method: "notifications/tools/list_changed" };
508
+ this.writeResponse(this.stdoutRef, notification);
509
+ this.logger.info("[mcp-bridge] Sent notifications/tools/list_changed");
510
+ }
497
511
  /** Extract server name from a tool name like "todoist_call" or "github_call" */
498
512
  guessServerFromToolName(toolName) {
499
513
  // Try exact match with placeholder pattern: serverName_call
@@ -538,6 +552,8 @@ export class StandaloneServer {
538
552
  // Cache tools to disk
539
553
  this.saveToolCache(serverName, tools);
540
554
  this.logger.info(`[mcp-bridge] Discovered ${tools.length} tools from ${serverName}`);
555
+ // Notify client that tool list changed (MCP spec: notifications/tools/list_changed)
556
+ this.sendToolsChanged();
541
557
  }
542
558
  catch (err) {
543
559
  this.logger.error(`[mcp-bridge] Failed to discover ${serverName}:`, err);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aiwerk/mcp-bridge",
3
- "version": "2.8.30",
3
+ "version": "2.8.31",
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",