@aiwerk/mcp-bridge 2.8.12 → 2.8.14

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.
@@ -98,6 +98,14 @@ function parseArgs(argv) {
98
98
  case "--offline":
99
99
  args.offline = true;
100
100
  break;
101
+ case "--register":
102
+ i++;
103
+ if (!argv[i]) {
104
+ process.stderr.write("Error: --register requires a client name (claude-code, codex, cursor, windsurf)\n");
105
+ process.exit(1);
106
+ }
107
+ args.register = argv[i];
108
+ break;
101
109
  case "--daily":
102
110
  i++;
103
111
  args.daily = parseInt(argv[i], 10);
@@ -171,7 +179,7 @@ Usage:
171
179
  mcp-bridge Start in stdio mode (default)
172
180
  mcp-bridge --sse --port 3000 Start as SSE server
173
181
  mcp-bridge --http --port 3000 Start as streamable-http server
174
- mcp-bridge init Create ~/.mcp-bridge/ with config template
182
+ mcp-bridge init [--register <client>] Create config + optionally register with a client
175
183
  mcp-bridge install <server> Install a server from the catalog
176
184
  mcp-bridge catalog [--offline] List available servers
177
185
  mcp-bridge servers List configured servers
@@ -203,109 +211,123 @@ function whichCmd(name) {
203
211
  return false;
204
212
  }
205
213
  }
206
- function cmdInit(logger) {
214
+ function cmdInit(logger, register) {
207
215
  initConfigDir(logger);
208
216
  const isGlobal = __dirname.includes("node_modules") && (__dirname.includes("/lib/node_modules/") || __dirname.includes("\\lib\\node_modules\\"));
209
217
  const bridgeCmd = isGlobal ? "mcp-bridge" : "node";
210
218
  const bridgeArgs = isGlobal ? ["serve"] : [join(__dirname, "..", "bin", "mcp-bridge.js"), "serve"];
211
- // Auto-detect and register with known clients
212
- let registered = false;
213
- // Claude Code
214
- if (whichCmd("claude")) {
215
- try {
216
- const addArgs = ["mcp", "add", "-s", "user", "mcp-bridge", "--", bridgeCmd, ...bridgeArgs];
217
- execFileSync("claude", addArgs, { stdio: "pipe" });
218
- process.stdout.write("✓ Registered with Claude Code (user scope) → ~/.claude.json\n Restart Claude Code to activate.\n");
219
- registered = true;
219
+ const cmd = isGlobal ? "mcp-bridge" : `node ${join(__dirname, "..", "bin", "mcp-bridge.js")}`;
220
+ if (register) {
221
+ registerClient(register, bridgeCmd, bridgeArgs, cmd);
222
+ return;
223
+ }
224
+ const detected = [];
225
+ if (whichCmd("claude"))
226
+ detected.push("claude-code");
227
+ if (whichCmd("codex"))
228
+ detected.push("codex");
229
+ if (existsSync(join(homedir(), ".cursor")))
230
+ detected.push("cursor");
231
+ if (existsSync(join(homedir(), ".windsurf")))
232
+ detected.push("windsurf");
233
+ if (detected.length > 0) {
234
+ process.stdout.write("\nDetected MCP clients. Register with:\n");
235
+ for (const client of detected) {
236
+ process.stdout.write(` mcp-bridge init --register ${client}\n`);
220
237
  }
221
- catch (err) {
222
- const msg = err instanceof Error ? err.message : String(err);
223
- if (msg.includes("already exists")) {
224
- registered = true;
225
- // Silent - already configured, no need to print
238
+ }
239
+ else {
240
+ process.stdout.write(`\nNo supported MCP client detected. Manual setup:\n\n Claude Code: claude mcp add -s user mcp-bridge -- ${cmd} serve\n Codex: codex mcp add mcp-bridge -- ${cmd} serve\n Cursor: Add to ~/.cursor/mcp.json\n Claude Desktop: Add to claude_desktop_config.json\n OpenClaw: openclaw plugins install @aiwerk/openclaw-mcp-bridge\n\nJSON config block (Cursor/Claude Desktop/Windsurf):\n\n {\n "mcp-bridge": {\n "command": "${isGlobal ? "mcp-bridge" : "node"}",\n "args": ${JSON.stringify(bridgeArgs)}\n }\n }\n`);
241
+ }
242
+ if (!isGlobal) {
243
+ process.stdout.write("\nTip: Install globally for a cleaner setup:\n npm install -g @aiwerk/mcp-bridge\n");
244
+ }
245
+ }
246
+ function registerClient(client, bridgeCmd, bridgeArgs, cmd) {
247
+ switch (client) {
248
+ case "claude-code": {
249
+ try {
250
+ execFileSync("claude", ["mcp", "add", "-s", "user", "mcp-bridge", "--", bridgeCmd, ...bridgeArgs], { stdio: "pipe" });
251
+ process.stdout.write("✓ Registered with Claude Code → ~/.claude.json\n Restart Claude Code to activate.\n");
226
252
  }
227
- else {
228
- process.stdout.write("⚠ Claude Code detected but registration failed. Manual setup:\n");
229
- process.stdout.write(` claude mcp add -s user mcp-bridge -- ${bridgeCmd} ${bridgeArgs.join(" ")}\n\n`);
253
+ catch (err) {
254
+ const msg = err instanceof Error ? err.message : String(err);
255
+ if (msg.includes("already exists")) {
256
+ process.stdout.write("✓ Claude Code already configured.\n");
257
+ }
258
+ else {
259
+ process.stdout.write(`⚠ Registration failed. Manual setup:\n claude mcp add -s user mcp-bridge -- ${cmd} serve\n`);
260
+ }
230
261
  }
262
+ break;
231
263
  }
232
- }
233
- // Cursor
234
- const cursorConfigPath = join(homedir(), ".cursor", "mcp.json");
235
- if (existsSync(join(homedir(), ".cursor"))) {
236
- try {
237
- let cursorConfig = {};
238
- if (existsSync(cursorConfigPath)) {
239
- cursorConfig = JSON.parse(readFileSync(cursorConfigPath, "utf-8"));
240
- }
241
- if (!cursorConfig.mcpServers)
242
- cursorConfig.mcpServers = {};
243
- if (!cursorConfig.mcpServers["mcp-bridge"]) {
244
- cursorConfig.mcpServers["mcp-bridge"] = { command: bridgeCmd, args: bridgeArgs };
245
- writeFileSync(cursorConfigPath, JSON.stringify(cursorConfig, null, 2) + "\n", "utf-8");
246
- process.stdout.write(`✓ Registered with Cursor → ${cursorConfigPath}\n Restart Cursor to activate.\n`);
247
- registered = true;
264
+ case "codex": {
265
+ const codexConfigPath = join(homedir(), ".codex", "config.toml");
266
+ try {
267
+ const codexConfig = existsSync(codexConfigPath) ? readFileSync(codexConfigPath, "utf-8") : "";
268
+ if (codexConfig.includes("[mcp_servers.mcp-bridge]") || codexConfig.includes("[mcp_servers.aiwerk-bridge]")) {
269
+ process.stdout.write("✓ Codex already configured.\n");
270
+ }
271
+ else {
272
+ execFileSync("codex", ["mcp", "add", "mcp-bridge", "--", bridgeCmd, ...bridgeArgs], { stdio: "pipe" });
273
+ process.stdout.write(`✓ Registered with Codex → ${codexConfigPath}\n Restart Codex to activate.\n`);
274
+ }
248
275
  }
249
- else {
250
- registered = true;
251
- // Silent - already configured
252
- registered = true;
276
+ catch {
277
+ process.stdout.write(`⚠ Registration failed. Manual setup:\n codex mcp add mcp-bridge -- ${cmd} serve\n`);
253
278
  }
279
+ break;
254
280
  }
255
- catch {
256
- process.stdout.write("⚠ Cursor detected but registration failed.\n");
257
- }
258
- }
259
- // Windsurf
260
- const windsurfConfigPath = join(homedir(), ".windsurf", "mcp.json");
261
- if (existsSync(join(homedir(), ".windsurf"))) {
262
- try {
263
- let wsConfig = {};
264
- if (existsSync(windsurfConfigPath)) {
265
- wsConfig = JSON.parse(readFileSync(windsurfConfigPath, "utf-8"));
281
+ case "cursor": {
282
+ const configPath = join(homedir(), ".cursor", "mcp.json");
283
+ try {
284
+ let config = {};
285
+ if (existsSync(configPath))
286
+ config = JSON.parse(readFileSync(configPath, "utf-8"));
287
+ if (!config.mcpServers)
288
+ config.mcpServers = {};
289
+ if (config.mcpServers["mcp-bridge"]) {
290
+ process.stdout.write("✓ Cursor already configured.\n");
291
+ }
292
+ else {
293
+ config.mcpServers["mcp-bridge"] = { command: bridgeCmd, args: bridgeArgs };
294
+ writeFileSync(configPath, JSON.stringify(config, null, 2) + "\n", "utf-8");
295
+ process.stdout.write(`✓ Registered with Cursor → ${configPath}\n Restart Cursor to activate.\n`);
296
+ }
266
297
  }
267
- if (!wsConfig.mcpServers)
268
- wsConfig.mcpServers = {};
269
- if (!wsConfig.mcpServers["mcp-bridge"]) {
270
- wsConfig.mcpServers["mcp-bridge"] = { command: bridgeCmd, args: bridgeArgs };
271
- writeFileSync(windsurfConfigPath, JSON.stringify(wsConfig, null, 2) + "\n", "utf-8");
272
- process.stdout.write(`✓ Registered with Windsurf → ${windsurfConfigPath}\n Restart Windsurf to activate.\n`);
273
- registered = true;
298
+ catch {
299
+ process.stdout.write("⚠ Cursor registration failed.\n");
274
300
  }
275
- else {
276
- registered = true;
277
- // Silent - already configured
278
- registered = true;
301
+ break;
302
+ }
303
+ case "windsurf": {
304
+ const configPath = join(homedir(), ".windsurf", "mcp.json");
305
+ try {
306
+ let config = {};
307
+ if (existsSync(configPath))
308
+ config = JSON.parse(readFileSync(configPath, "utf-8"));
309
+ if (!config.mcpServers)
310
+ config.mcpServers = {};
311
+ if (config.mcpServers["mcp-bridge"]) {
312
+ process.stdout.write("✓ Windsurf already configured.\n");
313
+ }
314
+ else {
315
+ config.mcpServers["mcp-bridge"] = { command: bridgeCmd, args: bridgeArgs };
316
+ writeFileSync(configPath, JSON.stringify(config, null, 2) + "\n", "utf-8");
317
+ process.stdout.write(`✓ Registered with Windsurf → ${configPath}\n Restart Windsurf to activate.\n`);
318
+ }
279
319
  }
320
+ catch {
321
+ process.stdout.write("⚠ Windsurf registration failed.\n");
322
+ }
323
+ break;
280
324
  }
281
- catch {
282
- process.stdout.write("⚠ Windsurf detected but registration failed.\n");
325
+ default: {
326
+ const isGlob = bridgeCmd === "mcp-bridge";
327
+ process.stdout.write(`Unknown client "${client}". Generic MCP config (add to your client's MCP settings):\n\n {\n "mcp-bridge": {\n "command": "${isGlob ? "mcp-bridge" : "node"}",\n "args": ${JSON.stringify(bridgeArgs)}\n }\n }\n\nKnown clients with auto-registration: claude-code, codex, cursor, windsurf\n`);
328
+ break;
283
329
  }
284
330
  }
285
- if (!registered) {
286
- const cmd = isGlobal ? "mcp-bridge" : `node ${join(__dirname, "..", "bin", "mcp-bridge.js")}`;
287
- process.stdout.write(`
288
- No supported MCP client detected. Add manually:
289
-
290
- Claude Code: claude mcp add -s user mcp-bridge -- ${cmd} serve
291
- Cursor: Add to ~/.cursor/mcp.json
292
- Claude Desktop: Add to claude_desktop_config.json
293
- OpenClaw: openclaw plugins install @aiwerk/openclaw-mcp-bridge
294
-
295
- JSON config block (Cursor/Claude Desktop/Windsurf):
296
-
297
- {
298
- "mcp-bridge": {
299
- "command": "${isGlobal ? "mcp-bridge" : "node"}",
300
- "args": ${JSON.stringify(bridgeArgs)}
301
- }
302
- }
303
- `);
304
- }
305
- if (!isGlobal) {
306
- process.stdout.write("\nTip: Install globally for a cleaner setup:\n npm install -g @aiwerk/mcp-bridge\n");
307
- }
308
- process.stdout.write("\nRestart your client. The bridge appears as an 'mcp' tool with\nsearch, install, and catalog actions to discover and add MCP servers.\n");
309
331
  }
310
332
  function cmdCatalog(logger) {
311
333
  const catalogPath = join(PACKAGE_ROOT, "servers", "index.json");
@@ -742,7 +764,7 @@ async function main() {
742
764
  printHelp();
743
765
  break;
744
766
  case "init":
745
- cmdInit(logger);
767
+ cmdInit(logger, args.register);
746
768
  break;
747
769
  case "catalog":
748
770
  cmdCatalog(logger);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aiwerk/mcp-bridge",
3
- "version": "2.8.12",
3
+ "version": "2.8.14",
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",