@aiwerk/mcp-bridge 2.8.35 → 2.8.37

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.
@@ -389,13 +389,15 @@ function cmdServers(logger, configPath) {
389
389
  process.stdout.write("No servers configured.\n");
390
390
  return;
391
391
  }
392
- process.stdout.write("\nConfigured servers:\n\n");
393
- process.stdout.write(" Server Transport Description\n");
394
- process.stdout.write(" " + "".repeat(60) + "\n");
392
+ const maxName = Math.max(8, ...entries.map(([n]) => n.length)) + 2;
393
+ process.stdout.write(`\nConfigured servers (${entries.length}):\n\n`);
394
+ process.stdout.write(` ${"Server".padEnd(maxName)}${"Transport".padEnd(14)}Description\n`);
395
+ process.stdout.write(" " + "─".repeat(maxName + 14 + 40) + "\n");
395
396
  for (const [name, serverConfig] of entries) {
396
- const padded = name.padEnd(16);
397
- const transport = serverConfig.transport.padEnd(13);
398
- process.stdout.write(` ${padded}${transport}${serverConfig.description || ""}\n`);
397
+ const padded = name.padEnd(maxName);
398
+ const transport = serverConfig.transport.padEnd(14);
399
+ const desc = (serverConfig.description || "").slice(0, 60);
400
+ process.stdout.write(` ${padded}${transport}${desc}\n`);
399
401
  }
400
402
  process.stdout.write("\n");
401
403
  }
@@ -31,6 +31,8 @@ export declare class StandaloneServer {
31
31
  /** Connect to all backend servers and discover their tools (direct mode). */
32
32
  private discoverDirectTools;
33
33
  private _doDiscovery;
34
+ /** The mcp_manage tool definition for direct mode */
35
+ private getMcpManageTool;
34
36
  /** Send notifications/tools/list_changed to the client via stdout */
35
37
  private sendToolsChanged;
36
38
  /** Extract server name from a tool name like "todoist_call" or "github_call" */
@@ -258,6 +258,7 @@ export class StandaloneServer {
258
258
  description: t.description,
259
259
  inputSchema: t.inputSchema
260
260
  }));
261
+ tools.push(this.getMcpManageTool());
261
262
  return { jsonrpc: "2.0", id, result: { tools } };
262
263
  }
263
264
  // Lazy: try cache first, add discover tool for uncached servers
@@ -306,6 +307,7 @@ export class StandaloneServer {
306
307
  }
307
308
  });
308
309
  }
310
+ lazyTools.push(this.getMcpManageTool());
309
311
  return { jsonrpc: "2.0", id, result: { tools: lazyTools } };
310
312
  }
311
313
  async handleToolsCall(id, params) {
@@ -349,7 +351,48 @@ export class StandaloneServer {
349
351
  }
350
352
  };
351
353
  }
352
- // Handle mcp_discover tool
354
+ // Handle mcp_manage tool (direct mode management)
355
+ if (toolName === "mcp_manage") {
356
+ const action = toolArgs?.action;
357
+ const server = toolArgs?.server;
358
+ const query = toolArgs?.query;
359
+ if (action === "servers" || action === "status") {
360
+ const entries = Object.entries(this.config.servers).map(([name, cfg]) => {
361
+ const connected = this.directConnections.get(name)?.initialized ? "connected" : "not connected";
362
+ return `${name} (${cfg.transport}, ${connected}): ${cfg.description || ""}`;
363
+ });
364
+ return { jsonrpc: "2.0", id, result: { content: [{ type: "text", text: entries.length > 0 ? `Configured servers:\n\n${entries.join("\n")}` : "No servers configured." }] } };
365
+ }
366
+ if (action === "discover" && server) {
367
+ await this.discoverSingleServer(server);
368
+ const serverTools = this.directTools.filter(t => t.serverName === server);
369
+ return { jsonrpc: "2.0", id, result: { content: [{ type: "text", text: `Discovered ${serverTools.length} tools from "${server}":\n\n${serverTools.map(t => `${t.registeredName}: ${t.description}`).join("\n")}` }] } };
370
+ }
371
+ if (action === "search" || action === "install" || action === "catalog" || action === "set-mode" || action === "remove") {
372
+ // Delegate to router dispatch (create a temporary router for management actions)
373
+ if (!this.router) {
374
+ const { McpRouter } = await import("./mcp-router.js");
375
+ this.router = new McpRouter(this.config.servers, this.config, this.logger);
376
+ }
377
+ const params = {};
378
+ if (query)
379
+ params.query = query;
380
+ if (server)
381
+ params.server = server;
382
+ if (server)
383
+ params.name = server;
384
+ if (toolArgs?.mode)
385
+ params.mode = toolArgs.mode;
386
+ const result = await this.router.dispatch(server, action, undefined, params);
387
+ // If install succeeded, notify about new tools
388
+ if (action === "install" && "installed" in result && result.installed) {
389
+ this.sendToolsChanged();
390
+ }
391
+ return { jsonrpc: "2.0", id, result: { content: [{ type: "text", text: JSON.stringify(result) }] } };
392
+ }
393
+ return { jsonrpc: "2.0", id, result: { content: [{ type: "text", text: "Unknown action. Use: search, install, remove, catalog, status, servers, discover, set-mode" }] } };
394
+ }
395
+ // Handle mcp_discover tool (legacy, kept for backward compatibility)
353
396
  if (toolName === "mcp_discover") {
354
397
  const serverName = toolArgs?.server;
355
398
  if (!serverName || !this.config.servers[serverName]) {
@@ -515,6 +558,24 @@ export class StandaloneServer {
515
558
  }
516
559
  }
517
560
  }
561
+ /** The mcp_manage tool definition for direct mode */
562
+ getMcpManageTool() {
563
+ const serverNames = Object.keys(this.config.servers);
564
+ return {
565
+ name: "mcp_manage",
566
+ description: `MCP server manager. Actions: 'search' to find servers in the verified catalog (100+ signed recipes), 'install' to add a server by name, 'remove' to remove a server, 'catalog' to browse all, 'status' to check connections, 'servers' to list configured servers, 'discover' to connect a server and discover its tools, 'set-mode' to switch between router/direct mode. Connected servers: ${serverNames.join(", ") || "none"}.`,
567
+ inputSchema: {
568
+ type: "object",
569
+ properties: {
570
+ action: { type: "string", description: "search | install | remove | catalog | status | servers | discover | set-mode", enum: ["search", "install", "remove", "catalog", "status", "servers", "discover", "set-mode"] },
571
+ server: { type: "string", description: "Server name (for install, remove, discover)" },
572
+ query: { type: "string", description: "Search query (for action=search)" },
573
+ mode: { type: "string", description: "Mode (for action=set-mode): router or direct", enum: ["router", "direct"] }
574
+ },
575
+ required: ["action"]
576
+ }
577
+ };
578
+ }
518
579
  /** Send notifications/tools/list_changed to the client via stdout */
519
580
  sendToolsChanged() {
520
581
  if (!this.stdoutRef)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aiwerk/mcp-bridge",
3
- "version": "2.8.35",
3
+ "version": "2.8.37",
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",