mcp-cross 1.1.0 → 1.2.0-beta.1

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/LICENSE CHANGED
File without changes
package/README.md CHANGED
@@ -404,6 +404,8 @@ GitHub MCP Server (api.githubcopilot.com)
404
404
 
405
405
  Use these tested command lines when mirroring Claude Desktop’s configuration. Each snippet lists every flag that must be present for the server to launch successfully under Windows → WSL bridging.
406
406
 
407
+ > **Windows quoting fix:** Claude Desktop launches stdio servers through `cmd.exe`. When it resolves `command: "npx"` to `C:\Program Files\nodejs\npx.cmd` the resulting command line is emitted without quotes, leading to the classic `'C:\Program' is not recognized` failure. Wrap every `npx` invocation inside `powershell.exe -NoLogo -NoProfile -Command "& { ... }"` so PowerShell handles the quoting before `cmd.exe` runs it.
408
+
407
409
  #### 1. Ghostis Brain (Python + WSL)
408
410
 
409
411
  Requirements:
@@ -424,11 +426,12 @@ Claude config fragment:
424
426
 
425
427
  ```json
426
428
  "ghostis-brain": {
427
- "command": "npx",
429
+ "command": "powershell.exe",
428
430
  "args": [
429
- "-y", "mcp-cross@latest",
430
- "--wsl", "--shell", "zsh",
431
- "--", "python3", "-m", "ghostis.mcp"
431
+ "-NoLogo",
432
+ "-NoProfile",
433
+ "-Command",
434
+ "& { npx -y mcp-cross@latest --wsl --shell zsh -- python3 -m ghostis.mcp }"
432
435
  ],
433
436
  "env": {
434
437
  "GHOSTIS_STORAGE_DIR": "/home/epps/.ghostis/memory",
@@ -456,14 +459,12 @@ Claude config fragment:
456
459
 
457
460
  ```json
458
461
  "filesystem": {
459
- "command": "npx",
462
+ "command": "powershell.exe",
460
463
  "args": [
461
- "-y", "mcp-cross@latest",
462
- "--wsl", "--shell", "zsh",
463
- "--",
464
- "npx", "-y", "@modelcontextprotocol/server-filesystem",
465
- "C:\\Users\\seane\\dev",
466
- "/mnt/dev/workspaces"
464
+ "-NoLogo",
465
+ "-NoProfile",
466
+ "-Command",
467
+ "& { npx -y mcp-cross@latest --wsl --shell zsh -- npx -y @modelcontextprotocol/server-filesystem C:\\Users\\seane\\dev /mnt/dev/workspaces }"
467
468
  ]
468
469
  }
469
470
  ```
@@ -487,18 +488,17 @@ Claude config fragment:
487
488
 
488
489
  ```json
489
490
  "github-mcp-server": {
490
- "command": "npx",
491
+ "command": "powershell.exe",
491
492
  "args": [
492
- "-y", "mcp-cross@latest",
493
- "--debug",
494
- "--wsl", "--shell", "zsh",
495
- "--http", "https://api.githubcopilot.com/mcp/",
496
- "--header", "Authorization: Bearer $GH_TOKEN"
493
+ "-NoLogo",
494
+ "-NoProfile",
495
+ "-Command",
496
+ "& { npx -y mcp-cross@latest --debug --wsl --shell zsh --http https://api.githubcopilot.com/mcp/ --header 'Authorization: Bearer $GH_TOKEN' }"
497
497
  ]
498
498
  }
499
499
  ```
500
500
 
501
- > **Tip:** When testing from Windows PowerShell, keep the `$GH_TOKEN` literal inside single quotes and pass the actual value with `--env GH_TOKEN=$env:GH_TOKEN` so the proxy can expand it inside WSL exactly like Claude does.
501
+ > **Tip:** When using the PowerShell wrapper (either manually or via Claude), keep `$GH_TOKEN` inside single quotes and pass the actual value with `--env GH_TOKEN=$env:GH_TOKEN` so the proxy can expand it inside WSL exactly like Claude does.
502
502
 
503
503
  ### Bridge Usage
504
504
 
@@ -527,12 +527,12 @@ mcp-cross --wsl cat C:\data.txt
527
527
  {
528
528
  "mcpServers": {
529
529
  "wsl-server": {
530
- "command": "npx",
530
+ "command": "powershell.exe",
531
531
  "args": [
532
- "mcp-cross",
533
- "--wsl",
534
- "node",
535
- "/home/user/server.js"
532
+ "-NoLogo",
533
+ "-NoProfile",
534
+ "-Command",
535
+ "& { npx -y mcp-cross@latest --wsl node /home/user/server.js }"
536
536
  ]
537
537
  }
538
538
  }
@@ -659,6 +659,24 @@ Check the debug output for:
659
659
  - Command resolution problems
660
660
  - Process spawning errors
661
661
 
662
+ ### `'C:\\Program' is not recognized`
663
+
664
+ This happens when Claude Desktop (or any Windows host that shells through `cmd.exe`) resolves `command: "npx"` to `C:\Program Files\nodejs\npx.cmd` and runs it without surrounding quotes. Windows interprets everything up to the first space as the executable name, so `cmd.exe` tries to launch `C:\Program` and immediately fails.
665
+
666
+ **Fix:** Wrap the entire `npx` invocation inside PowerShell so the quoting happens before `cmd.exe` ever sees the command line:
667
+
668
+ ```json
669
+ "command": "powershell.exe",
670
+ "args": [
671
+ "-NoLogo",
672
+ "-NoProfile",
673
+ "-Command",
674
+ "& { npx -y mcp-cross@latest --wsl --shell zsh -- ... }"
675
+ ]
676
+ ```
677
+
678
+ All Claude Desktop examples in this README already use that wrapper. If you still prefer `command: "npx"`, move your Node.js installation to a path without spaces (or set `command` to a short path such as `C:\npx\npx.cmd`).
679
+
662
680
  ### Windows Executable Not Found in WSL
663
681
 
664
682
  Ensure:
File without changes
File without changes
@@ -2,37 +2,34 @@
2
2
  "mcpServers": {
3
3
  "github-mcp-via-wsl": {
4
4
  "type": "stdio",
5
- "command": "npx",
5
+ "command": "powershell.exe",
6
6
  "args": [
7
- "-y",
8
- "mcp-cross@latest",
9
- "--wsl",
10
- "--http", "https://api.githubcopilot.com/mcp/",
11
- "--header", "Authorization: Bearer $GH_TOKEN"
7
+ "-NoLogo",
8
+ "-NoProfile",
9
+ "-Command",
10
+ "& { npx -y mcp-cross@latest --wsl --http https://api.githubcopilot.com/mcp/ --header 'Authorization: Bearer $GH_TOKEN' }"
12
11
  ],
13
12
  "comment": "Access GitHub MCP server with token stored in WSL environment"
14
13
  },
15
14
  "custom-mcp-server": {
16
15
  "type": "stdio",
17
- "command": "npx",
16
+ "command": "powershell.exe",
18
17
  "args": [
19
- "-y",
20
- "mcp-cross@latest",
21
- "--http", "https://api.example.com/mcp/",
22
- "--header", "Authorization: Bearer $API_TOKEN",
23
- "--header", "X-Tenant-ID: $TENANT_ID",
24
- "--timeout", "30000"
18
+ "-NoLogo",
19
+ "-NoProfile",
20
+ "-Command",
21
+ "& { npx -y mcp-cross@latest --http https://api.example.com/mcp/ --header 'Authorization: Bearer $API_TOKEN' --header 'X-Tenant-ID: $TENANT_ID' --timeout 30000 }"
25
22
  ],
26
23
  "comment": "HTTP MCP server with multiple custom headers"
27
24
  },
28
25
  "local-debug": {
29
26
  "type": "stdio",
30
- "command": "npx",
27
+ "command": "powershell.exe",
31
28
  "args": [
32
- "-y",
33
- "mcp-cross@latest",
34
- "--debug",
35
- "--http", "http://localhost:3000/mcp"
29
+ "-NoLogo",
30
+ "-NoProfile",
31
+ "-Command",
32
+ "& { npx -y mcp-cross@latest --debug --http http://localhost:3000/mcp }"
36
33
  ],
37
34
  "comment": "Local MCP server for debugging (HTTP allowed for localhost)"
38
35
  }
@@ -1,48 +1,42 @@
1
1
  {
2
2
  "mcpServers": {
3
3
  "filesystem": {
4
- "command": "npx",
4
+ "command": "powershell.exe",
5
5
  "args": [
6
- "mcp-cross",
7
- "--",
8
- "npx",
9
- "-y",
10
- "@modelcontextprotocol/server-filesystem",
11
- "/Users/username/Documents"
6
+ "-NoLogo",
7
+ "-NoProfile",
8
+ "-Command",
9
+ "& { npx -y mcp-cross@latest -- npx -y @modelcontextprotocol/server-filesystem /Users/username/Documents }"
12
10
  ]
13
11
  },
14
12
  "brave-search": {
15
- "command": "npx",
13
+ "command": "powershell.exe",
16
14
  "args": [
17
- "mcp-cross",
18
- "--",
19
- "npx",
20
- "-y",
21
- "@modelcontextprotocol/server-brave-search"
15
+ "-NoLogo",
16
+ "-NoProfile",
17
+ "-Command",
18
+ "& { npx -y mcp-cross@latest -- npx -y @modelcontextprotocol/server-brave-search }"
22
19
  ],
23
20
  "env": {
24
21
  "BRAVE_API_KEY": "your-api-key-here"
25
22
  }
26
23
  },
27
24
  "custom-nodejs-server": {
28
- "command": "npx",
25
+ "command": "powershell.exe",
29
26
  "args": [
30
- "mcp-cross",
31
- "--",
32
- "node",
33
- "/path/to/your/server.js",
34
- "--config",
35
- "production"
27
+ "-NoLogo",
28
+ "-NoProfile",
29
+ "-Command",
30
+ "& { npx -y mcp-cross@latest -- node /path/to/your/server.js --config production }"
36
31
  ]
37
32
  },
38
33
  "with-debug": {
39
- "command": "npx",
34
+ "command": "powershell.exe",
40
35
  "args": [
41
- "mcp-cross",
42
- "--debug",
43
- "--",
44
- "node",
45
- "/path/to/server.js"
36
+ "-NoLogo",
37
+ "-NoProfile",
38
+ "-Command",
39
+ "& { npx -y mcp-cross@latest --debug -- node /path/to/server.js }"
46
40
  ]
47
41
  }
48
42
  }
File without changes
File without changes
File without changes
File without changes
package/index.js CHANGED
@@ -10,6 +10,23 @@ const { platform } = require('os');
10
10
  const wslBridge = require('./src/lib/wsl-bridge');
11
11
  const { startHttpProxy } = require('./src/lib/http-proxy');
12
12
 
13
+ function extractEnvVarsFromStrings(strings) {
14
+ if (!Array.isArray(strings)) return [];
15
+ const vars = new Set();
16
+ for (const value of strings) {
17
+ if (typeof value !== 'string') continue;
18
+ const regex = /\$\{([A-Za-z_][A-Za-z0-9_]*)(?::-[^}]*)?\}|\$([A-Za-z_][A-Za-z0-9_]*)/g;
19
+ let match;
20
+ while ((match = regex.exec(value)) !== null) {
21
+ const name = match[1] || match[2];
22
+ if (name) {
23
+ vars.add(name);
24
+ }
25
+ }
26
+ }
27
+ return Array.from(vars);
28
+ }
29
+
13
30
  /**
14
31
  * mcp-cross - Cross-platform MCP server bridge
15
32
  *
@@ -398,6 +415,17 @@ async function main() {
398
415
  wslArgs.push('--debug');
399
416
  }
400
417
 
418
+ if (mcpCrossOptions.includes('--debug')) {
419
+ const debugVars = extractEnvVarsFromStrings(httpHeaders);
420
+ if (debugVars.length > 0) {
421
+ const existing = customEnv.MCP_CROSS_DEBUG_VARS
422
+ ? customEnv.MCP_CROSS_DEBUG_VARS.split(',').map(v => v.trim()).filter(Boolean)
423
+ : [];
424
+ const merged = new Set([...existing, ...debugVars]);
425
+ customEnv.MCP_CROSS_DEBUG_VARS = Array.from(merged).join(',');
426
+ }
427
+ }
428
+
401
429
  try {
402
430
  await wslBridge.execute(wslCommand, wslArgs, mcpCrossOptions, customEnv);
403
431
  } catch (err) {
@@ -429,6 +457,16 @@ async function main() {
429
457
 
430
458
  // Check for WSL bridge mode (process bridge)
431
459
  if (mcpCrossOptions.includes('--wsl')) {
460
+ if (mcpCrossOptions.includes('--debug')) {
461
+ const debugVars = extractEnvVarsFromStrings([serverCommand, ...serverArgs]);
462
+ if (debugVars.length > 0) {
463
+ const existing = customEnv.MCP_CROSS_DEBUG_VARS
464
+ ? customEnv.MCP_CROSS_DEBUG_VARS.split(',').map(v => v.trim()).filter(Boolean)
465
+ : [];
466
+ const merged = new Set([...existing, ...debugVars]);
467
+ customEnv.MCP_CROSS_DEBUG_VARS = Array.from(merged).join(',');
468
+ }
469
+ }
432
470
  try {
433
471
  await wslBridge.execute(serverCommand, serverArgs, mcpCrossOptions, customEnv);
434
472
  } catch (err) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mcp-cross",
3
- "version": "1.1.0",
3
+ "version": "1.2.0-beta.1",
4
4
  "description": "Cross-platform MCP server bridge for seamless stdio communication across different environments",
5
5
  "author": "Sean Epping",
6
6
  "license": "MIT",
File without changes
File without changes
File without changes
File without changes
File without changes
@@ -33,6 +33,31 @@ fi
33
33
  if [ -n "${MCP_CROSS_DEBUG-}" ]; then
34
34
  echo "DEBUG: FILTERED PATH=" >&2
35
35
  printenv PATH >&2
36
+
37
+ if [ -n "${MCP_CROSS_DEBUG_VARS-}" ]; then
38
+ OLD_IFS_ENV="$IFS"
39
+ IFS=','
40
+ read -ra DEBUG_VARS <<< "$MCP_CROSS_DEBUG_VARS"
41
+ IFS="$OLD_IFS_ENV"
42
+
43
+ for rawVar in "${DEBUG_VARS[@]}"; do
44
+ var="$(echo "$rawVar" | xargs)"
45
+ if [ -z "$var" ]; then
46
+ continue
47
+ fi
48
+
49
+ if [ -z "${!var+x}" ]; then
50
+ echo "DEBUG: ENV[$var]=<unset>" >&2
51
+ else
52
+ value="${!var}"
53
+ if [ -z "$value" ]; then
54
+ echo "DEBUG: ENV[$var]=<empty>" >&2
55
+ else
56
+ echo "DEBUG: ENV[$var]=<set length=${#value}>" >&2
57
+ fi
58
+ fi
59
+ done
60
+ fi
36
61
  fi
37
62
 
38
63
  # Exec the provided command