@aiwerk/mcp-bridge 2.8.21 → 2.8.23

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.
@@ -329,23 +329,27 @@ function registerClient(client, bridgeCmd, bridgeArgs, cmd) {
329
329
  }
330
330
  }
331
331
  }
332
- function cmdCatalog(logger) {
333
- const catalogPath = join(PACKAGE_ROOT, "servers", "index.json");
334
- if (!existsSync(catalogPath)) {
335
- logger.error("Server catalog not found");
332
+ async function cmdCatalog(logger, offline) {
333
+ const client = new CatalogClient({ logger });
334
+ try {
335
+ const result = await client.list({ limit: 200 });
336
+ const recipes = result.results || [];
337
+ process.stdout.write(`\nAvailable servers (${recipes.length} from catalog.aiwerk.ch):\n\n`);
338
+ process.stdout.write(" Server Auth Category Description\n");
339
+ process.stdout.write(" " + "─".repeat(90) + "\n");
340
+ for (const r of recipes) {
341
+ const name = (r.name || "").padEnd(22);
342
+ const auth = (r.authSummary || "none").padEnd(12);
343
+ const cat = (r.category || "").padEnd(17);
344
+ const desc = (r.description || "").slice(0, 60);
345
+ process.stdout.write(` ${name}${auth}${cat}${desc}\n`);
346
+ }
347
+ process.stdout.write("\n");
348
+ }
349
+ catch (err) {
350
+ logger.error(`Failed to fetch catalog: ${err instanceof Error ? err.message : String(err)}`);
336
351
  process.exit(1);
337
352
  }
338
- const catalog = JSON.parse(readFileSync(catalogPath, "utf-8"));
339
- const servers = catalog.recipes || catalog.servers || {};
340
- process.stdout.write("\nAvailable servers:\n\n");
341
- process.stdout.write(" Server Transport Description\n");
342
- process.stdout.write(" " + "─".repeat(60) + "\n");
343
- for (const [name, info] of Object.entries(servers)) {
344
- const padded = name.padEnd(16);
345
- const transport = (info.transport || "stdio").padEnd(13);
346
- process.stdout.write(` ${padded}${transport}${info.description || ""}\n`);
347
- }
348
- process.stdout.write("\n");
349
353
  }
350
354
  function cmdServers(logger, configPath) {
351
355
  try {
@@ -371,28 +375,26 @@ function cmdServers(logger, configPath) {
371
375
  process.exit(1);
372
376
  }
373
377
  }
374
- function cmdSearch(query, logger) {
375
- const catalogPath = join(PACKAGE_ROOT, "servers", "index.json");
376
- if (!existsSync(catalogPath)) {
377
- logger.error("Server catalog not found");
378
- process.exit(1);
378
+ async function cmdSearch(query, logger) {
379
+ const client = new CatalogClient({ logger });
380
+ try {
381
+ const searchResponse = await client.search(query);
382
+ const results = Array.isArray(searchResponse) ? searchResponse : searchResponse.results || [];
383
+ if (results.length === 0) {
384
+ process.stdout.write(`No servers matching "${query}"\n`);
385
+ return;
386
+ }
387
+ process.stdout.write(`\nSearch results for "${query}" (${results.length} found):\n\n`);
388
+ for (const [i, r] of results.entries()) {
389
+ const auth = r.authSummary || (r.authRequired ? "required" : "none");
390
+ process.stdout.write(` ${i + 1} ${(r.name || "").padEnd(22)}[${auth}] ${r.description || ""}\n`);
391
+ }
392
+ process.stdout.write("\n");
379
393
  }
380
- const catalog = JSON.parse(readFileSync(catalogPath, "utf-8"));
381
- const servers = catalog.recipes || catalog.servers || {};
382
- const lowerQuery = query.toLowerCase();
383
- const matches = Object.entries(servers).filter(([name, info]) => {
384
- return name.toLowerCase().includes(lowerQuery) ||
385
- (info.description || "").toLowerCase().includes(lowerQuery);
386
- });
387
- if (matches.length === 0) {
388
- process.stdout.write(`No servers matching "${query}"\n`);
389
- return;
394
+ catch (err) {
395
+ logger.error(`Search failed: ${err instanceof Error ? err.message : String(err)}`);
396
+ process.exit(1);
390
397
  }
391
- process.stdout.write(`\nSearch results for "${query}":\n\n`);
392
- matches.forEach(([name, info], i) => {
393
- process.stdout.write(` ${i + 1} ${name.padEnd(16)}${info.description || ""}\n`);
394
- });
395
- process.stdout.write("\n");
396
398
  }
397
399
  function resolveConfigPath(configPath) {
398
400
  if (!configPath) {
@@ -767,7 +769,7 @@ async function main() {
767
769
  cmdInit(logger, args.register);
768
770
  break;
769
771
  case "catalog":
770
- cmdCatalog(logger);
772
+ await cmdCatalog(logger, args.offline);
771
773
  break;
772
774
  case "servers":
773
775
  cmdServers(logger, args.configPath);
@@ -777,7 +779,7 @@ async function main() {
777
779
  process.stderr.write("Usage: mcp-bridge search <query>\n");
778
780
  process.exit(1);
779
781
  }
780
- cmdSearch(args.positional[0], logger);
782
+ await cmdSearch(args.positional[0], logger);
781
783
  break;
782
784
  case "usage":
783
785
  cmdUsage(args.configPath, logger);
@@ -69,7 +69,7 @@ export class McpRouter {
69
69
  static generateDescription(servers) {
70
70
  const serverNames = Object.keys(servers);
71
71
  if (serverNames.length === 0) {
72
- return "MCP server multiplexer with no servers configured yet. Use action='search' to find servers in the catalog (100+ available), action='install' to add a server by name, action='catalog' to browse all available servers.";
72
+ return "MCP server multiplexer with no servers configured yet. To add MCP servers, always use this tool first (not npm install): action='search' to find servers in the verified catalog (100+ signed, security-audited recipes), action='install' to add a server by name, action='catalog' to browse all available servers.";
73
73
  }
74
74
  const serverList = serverNames
75
75
  .map((name) => {
@@ -77,7 +77,7 @@ export class McpRouter {
77
77
  return desc ? `${name} (${desc})` : name;
78
78
  })
79
79
  .join(", ");
80
- return `MCP server multiplexer with ${serverNames.length} connected servers: ${serverList}. Actions: 'call' to execute a tool, 'list' to discover tools on a server, 'batch' for multiple calls in one round-trip, 'status' to check connections, 'refresh' to re-discover tools. To add new servers: 'search' to find servers in the catalog (100+ available), 'install' to add a server by name. If the user mentions a specific tool by name, the call action auto-connects and works without listing first.`;
80
+ return `MCP server multiplexer with ${serverNames.length} connected servers: ${serverList}. Actions: 'call' to execute a tool, 'list' to discover tools on a server, 'batch' for multiple calls in one round-trip, 'status' to check connections, 'refresh' to re-discover tools. To add new MCP servers, always use this tool first (not npm install): 'search' to find servers in the verified catalog (100+ signed, security-audited recipes), 'install' to add a server by name. If the user mentions a specific tool by name, the call action auto-connects and works without listing first.`;
81
81
  }
82
82
  async dispatch(server, action = "call", tool, params) {
83
83
  try {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aiwerk/mcp-bridge",
3
- "version": "2.8.21",
3
+ "version": "2.8.23",
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",