@aiwerk/mcp-bridge 2.8.7 → 2.8.8
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/dist/bin/mcp-bridge.js +93 -12
- package/package.json +1 -1
package/dist/bin/mcp-bridge.js
CHANGED
|
@@ -3,6 +3,7 @@ import { readFileSync, existsSync, writeFileSync, mkdirSync } from "fs";
|
|
|
3
3
|
import { join, dirname, resolve, extname } from "path";
|
|
4
4
|
import { fileURLToPath } from "url";
|
|
5
5
|
import { homedir } from "os";
|
|
6
|
+
import { execFileSync, execSync } from "child_process";
|
|
6
7
|
import { loadConfig, initConfigDir, warnDeprecatedBundledRecipes, recipeToServerConfig, collectRequiredEnvVars } from "../src/config.js";
|
|
7
8
|
import { StandaloneServer } from "../src/standalone-server.js";
|
|
8
9
|
import { PACKAGE_VERSION } from "../src/protocol.js";
|
|
@@ -193,34 +194,109 @@ Options:
|
|
|
193
194
|
All logs go to stderr. Stdout is reserved for the MCP protocol (stdio mode).
|
|
194
195
|
`);
|
|
195
196
|
}
|
|
197
|
+
function whichCmd(name) {
|
|
198
|
+
try {
|
|
199
|
+
execSync(`which ${name}`, { stdio: "ignore" });
|
|
200
|
+
return true;
|
|
201
|
+
}
|
|
202
|
+
catch {
|
|
203
|
+
return false;
|
|
204
|
+
}
|
|
205
|
+
}
|
|
196
206
|
function cmdInit(logger) {
|
|
197
207
|
initConfigDir(logger);
|
|
198
|
-
// Detect global install: check if we're in a global node_modules (not under a project)
|
|
199
|
-
// Global paths: ~/.nvm/.../lib/node_modules, /usr/lib/node_modules, etc.
|
|
200
|
-
// Local paths: ~/projects/.../node_modules, ~/node_modules/
|
|
201
208
|
const isGlobal = __dirname.includes("node_modules") && (__dirname.includes("/lib/node_modules/") || __dirname.includes("\\lib\\node_modules\\"));
|
|
202
|
-
const
|
|
203
|
-
|
|
204
|
-
|
|
209
|
+
const bridgeCmd = isGlobal ? "mcp-bridge" : "node";
|
|
210
|
+
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)\n");
|
|
219
|
+
registered = true;
|
|
220
|
+
}
|
|
221
|
+
catch {
|
|
222
|
+
process.stdout.write("⚠ Claude Code detected but registration failed. Manual setup:\n");
|
|
223
|
+
process.stdout.write(` claude mcp add -s user mcp-bridge -- ${bridgeCmd} ${bridgeArgs.join(" ")}\n\n`);
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
// Cursor
|
|
227
|
+
const cursorConfigPath = join(homedir(), ".cursor", "mcp.json");
|
|
228
|
+
if (existsSync(join(homedir(), ".cursor"))) {
|
|
229
|
+
try {
|
|
230
|
+
let cursorConfig = {};
|
|
231
|
+
if (existsSync(cursorConfigPath)) {
|
|
232
|
+
cursorConfig = JSON.parse(readFileSync(cursorConfigPath, "utf-8"));
|
|
233
|
+
}
|
|
234
|
+
if (!cursorConfig.mcpServers)
|
|
235
|
+
cursorConfig.mcpServers = {};
|
|
236
|
+
if (!cursorConfig.mcpServers["mcp-bridge"]) {
|
|
237
|
+
cursorConfig.mcpServers["mcp-bridge"] = { command: bridgeCmd, args: bridgeArgs };
|
|
238
|
+
writeFileSync(cursorConfigPath, JSON.stringify(cursorConfig, null, 2) + "\n", "utf-8");
|
|
239
|
+
process.stdout.write("✓ Registered with Cursor\n");
|
|
240
|
+
registered = true;
|
|
241
|
+
}
|
|
242
|
+
else {
|
|
243
|
+
process.stdout.write("✓ Cursor already configured\n");
|
|
244
|
+
registered = true;
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
catch {
|
|
248
|
+
process.stdout.write("⚠ Cursor detected but registration failed.\n");
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
// Windsurf
|
|
252
|
+
const windsurfConfigPath = join(homedir(), ".windsurf", "mcp.json");
|
|
253
|
+
if (existsSync(join(homedir(), ".windsurf"))) {
|
|
254
|
+
try {
|
|
255
|
+
let wsConfig = {};
|
|
256
|
+
if (existsSync(windsurfConfigPath)) {
|
|
257
|
+
wsConfig = JSON.parse(readFileSync(windsurfConfigPath, "utf-8"));
|
|
258
|
+
}
|
|
259
|
+
if (!wsConfig.mcpServers)
|
|
260
|
+
wsConfig.mcpServers = {};
|
|
261
|
+
if (!wsConfig.mcpServers["mcp-bridge"]) {
|
|
262
|
+
wsConfig.mcpServers["mcp-bridge"] = { command: bridgeCmd, args: bridgeArgs };
|
|
263
|
+
writeFileSync(windsurfConfigPath, JSON.stringify(wsConfig, null, 2) + "\n", "utf-8");
|
|
264
|
+
process.stdout.write("✓ Registered with Windsurf\n");
|
|
265
|
+
registered = true;
|
|
266
|
+
}
|
|
267
|
+
else {
|
|
268
|
+
process.stdout.write("✓ Windsurf already configured\n");
|
|
269
|
+
registered = true;
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
catch {
|
|
273
|
+
process.stdout.write("⚠ Windsurf detected but registration failed.\n");
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
if (!registered) {
|
|
277
|
+
const cmd = isGlobal ? "mcp-bridge" : `node ${join(__dirname, "..", "bin", "mcp-bridge.js")}`;
|
|
278
|
+
process.stdout.write(`
|
|
279
|
+
No supported MCP client detected. Add manually:
|
|
205
280
|
|
|
206
281
|
Claude Code: claude mcp add -s user mcp-bridge -- ${cmd} serve
|
|
207
282
|
Cursor: Add to ~/.cursor/mcp.json
|
|
208
283
|
Claude Desktop: Add to claude_desktop_config.json
|
|
209
|
-
Windsurf: Add to ~/.windsurf/mcp.json
|
|
210
284
|
OpenClaw: openclaw plugins install @aiwerk/openclaw-mcp-bridge
|
|
211
285
|
|
|
212
|
-
|
|
286
|
+
JSON config block (Cursor/Claude Desktop/Windsurf):
|
|
213
287
|
|
|
214
288
|
{
|
|
215
289
|
"mcp-bridge": {
|
|
216
290
|
"command": "${isGlobal ? "mcp-bridge" : "node"}",
|
|
217
|
-
"args": ${
|
|
291
|
+
"args": ${JSON.stringify(bridgeArgs)}
|
|
218
292
|
}
|
|
219
293
|
}
|
|
220
|
-
${!isGlobal ? "\nTip: Install globally for a cleaner setup:\n npm install -g @aiwerk/mcp-bridge\n" : ""}
|
|
221
|
-
After adding, restart your client. The bridge will appear as an 'mcp' tool
|
|
222
|
-
with search, install, and catalog actions to discover and add MCP servers.
|
|
223
294
|
`);
|
|
295
|
+
}
|
|
296
|
+
if (!isGlobal) {
|
|
297
|
+
process.stdout.write("\nTip: Install globally for a cleaner setup:\n npm install -g @aiwerk/mcp-bridge\n");
|
|
298
|
+
}
|
|
299
|
+
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");
|
|
224
300
|
}
|
|
225
301
|
function cmdCatalog(logger) {
|
|
226
302
|
const catalogPath = join(PACKAGE_ROOT, "servers", "index.json");
|
|
@@ -605,6 +681,11 @@ async function cmdAuth(args, logger) {
|
|
|
605
681
|
process.stdout.write(`Authentication successful for ${serverName}. Token stored.\n`);
|
|
606
682
|
}
|
|
607
683
|
async function cmdServe(args, logger) {
|
|
684
|
+
// Auto-create config if missing (don't crash on first run)
|
|
685
|
+
const configPath = resolveConfigPath(args.configPath);
|
|
686
|
+
if (!existsSync(configPath)) {
|
|
687
|
+
initConfigDir(logger);
|
|
688
|
+
}
|
|
608
689
|
let config;
|
|
609
690
|
try {
|
|
610
691
|
config = loadConfig({ configPath: args.configPath, logger });
|