@aiwerk/mcp-bridge 2.8.24 → 2.8.25

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.
package/README.md CHANGED
@@ -417,9 +417,24 @@ Returns promoted tools (sorted by frequency) and full usage stats. All tracking
417
417
  | Mode | Tools exposed | Best for |
418
418
  |------|--------------|----------|
419
419
  | `router` (default) | Single `mcp` meta-tool | 3+ servers, token-conscious agents |
420
- | `direct` | All tools individually | Few servers, simple agents |
420
+ | `direct` | All tools individually | Clients with deferred/lazy tool loading (Claude Code), few servers |
421
421
 
422
- **Router mode** the agent calls `mcp(server="todoist", action="list")` to discover, then `mcp(server="todoist", tool="find-tasks", params={...})` to execute.
422
+ Switch modes via CLI or config:
423
+
424
+ ```bash
425
+ mcp-bridge init --mode direct # all tools exposed individually
426
+ mcp-bridge init --mode router # single mcp meta-tool (default)
427
+ ```
428
+
429
+ Or set in `~/.mcp-bridge/config.json`:
430
+
431
+ ```json
432
+ { "mode": "direct" }
433
+ ```
434
+
435
+ **Router mode** — the agent calls `mcp(server="todoist", action="list")` to discover, then `mcp(server="todoist", tool="find-tasks", params={...})` to execute. Best when you have many servers and want minimal token usage.
436
+
437
+ **Direct mode** — all tools from all servers are registered individually as `todoist_find_tasks`, `github_list_repos`, etc. The bridge still provides unified config, catalog install, OAuth2, security, retries, and reconnection. Ideal for clients that support deferred/lazy tool loading, where tools are registered but not loaded into context until needed.
423
438
 
424
439
  ### Multi-Server Tool Resolution
425
440
 
@@ -221,7 +221,7 @@ function whichCmd(name) {
221
221
  }
222
222
  function cmdInit(logger, register, mode) {
223
223
  initConfigDir(logger);
224
- // Apply --mode if config exists and mode was specified
224
+ // Apply --mode to config
225
225
  if (mode) {
226
226
  const configPath = join(homedir(), ".mcp-bridge", "config.json");
227
227
  if (existsSync(configPath)) {
@@ -236,6 +236,7 @@ function cmdInit(logger, register, mode) {
236
236
  catch { /* ignore parse errors */ }
237
237
  }
238
238
  }
239
+ // If --register is specified, do both mode + register
239
240
  const isGlobal = __dirname.includes("node_modules") && (__dirname.includes("/lib/node_modules/") || __dirname.includes("\\lib\\node_modules\\"));
240
241
  const bridgeCmd = isGlobal ? "mcp-bridge" : "node";
241
242
  const bridgeArgs = isGlobal ? ["serve"] : [join(__dirname, "..", "bin", "mcp-bridge.js"), "serve"];
@@ -110,6 +110,11 @@ export type RouterDispatchResponse = {
110
110
  message: string;
111
111
  missingEnvVars?: string[];
112
112
  credentialsUrl?: string;
113
+ } | {
114
+ action: "set-mode";
115
+ mode: string;
116
+ message: string;
117
+ requiresRestart?: boolean;
113
118
  } | {
114
119
  action: "intent";
115
120
  intent: string;
@@ -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 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.`;
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. Use 'set-mode' with params.mode='direct' to expose all tools individually (requires restart). 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 {
@@ -340,8 +340,41 @@ export class McpRouter {
340
340
  return this.error("connection_failed", `Failed to connect to ${server}: ${error instanceof Error ? error.message : String(error)}`);
341
341
  }
342
342
  }
343
+ // Set mode (persists to config, requires bridge restart to take effect)
344
+ if (normalizedAction === "set-mode") {
345
+ const newMode = params?.mode;
346
+ if (newMode !== "router" && newMode !== "direct") {
347
+ return this.error("invalid_params", "mode must be 'router' or 'direct'");
348
+ }
349
+ try {
350
+ const os = await import("os");
351
+ const fs = await import("fs");
352
+ const path = await import("path");
353
+ const configPath = path.join(os.homedir(), ".mcp-bridge", "config.json");
354
+ if (fs.existsSync(configPath)) {
355
+ const raw = JSON.parse(fs.readFileSync(configPath, "utf-8"));
356
+ const oldMode = raw.mode || "router";
357
+ if (oldMode === newMode) {
358
+ return { action: "set-mode", mode: newMode, message: `Already in "${newMode}" mode.` };
359
+ }
360
+ raw.mode = newMode;
361
+ fs.writeFileSync(configPath, JSON.stringify(raw, null, 2) + "\n", "utf-8");
362
+ this.logger.info(`Mode changed from "${oldMode}" to "${newMode}" in ${configPath}`);
363
+ return {
364
+ action: "set-mode",
365
+ mode: newMode,
366
+ message: `Mode changed to "${newMode}". Restart the bridge for changes to take effect.`,
367
+ requiresRestart: true,
368
+ };
369
+ }
370
+ return this.error("mcp_error", "Config file not found");
371
+ }
372
+ catch (err) {
373
+ return this.error("mcp_error", `Failed to set mode: ${err instanceof Error ? err.message : String(err)}`);
374
+ }
375
+ }
343
376
  if (normalizedAction !== "call") {
344
- return this.error("invalid_params", `action must be one of: list, call, batch, refresh, schema, intent, status, promotions, search, catalog, install`);
377
+ return this.error("invalid_params", `action must be one of: list, call, batch, refresh, schema, intent, status, promotions, search, catalog, install, set-mode`);
345
378
  }
346
379
  if (!tool) {
347
380
  return this.error("invalid_params", "tool is required for action=call");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aiwerk/mcp-bridge",
3
- "version": "2.8.24",
3
+ "version": "2.8.25",
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",