${userHome} on Windows isn't expanded in mcp config the same as on macOS / Linux

Where does the bug appear (feature/product)?

Cursor IDE

Describe the Bug

We’re having issues using out MCP config on Windows, it works fine on macOS / Linux, as well as in VS Code. On Cursor however it doesn’t work. We moved to use environment variables (which kind of is a hack) here as a work around: fix cursor plugin on windows by itsdouges · Pull Request #21 · paper-design/agent-plugins · GitHub

  • ${userHome} on Windows isn’t expanded the same as on macOS / Linux.
  • ${userHome} in mcp.json resolves to the URI path, not the filesystem path, so on Windows it becomes /c:/Users/ and every stdio server using it fails with spawn ENOENT. macOS/Linux are unaffected because the two forms coincide there. MCPService.resolveVariables uses IConfigurationResolverService.resolveAsync, whose userHome is built with home.path instead of home.fsPath

Here is a similar bug that were found in the ecosystem:

Steps to Reproduce

  • create a mcp.json with this content:

{ “mcpServers”: { “home-test”: { “command”: “${userHome}/AppData/Local/Programs/cursor/Cursor.exe”, “args”: [“–version”] } } }

Expected: spawns.
Actual: Output → MCP Logs shows Starting new stdio process with command: /c:/Users//AppData/… and spawn … ENOENT.

Add the contrast: ${env:USERPROFILE}/AppData/… works with the identical target, and ${userHome} works on macOS.

Expected Behavior

It should pick up the correct file path.

Operating System

Windows 10/11

Version Information

Cursor IDE: 3.21.16 (user setup)

Does this stop you from using Cursor

No - Cursor works, but with this issue

Hey @douges! On Windows ${userHome} in mcp.json comes through as /c:/Users/... instead of C:\Users\..., so stdio servers using it can’t spawn. That’s on our side, not your setup (macOS/Linux match up, so they’re unaffected), and it’s an issue we’re tracking.

Your env-var switch is the right call: ${env:USERPROFILE} on Windows / ${env:HOME} on macOS/Linux, or the combined ${env:HOME}${env:USERPROFILE}/... for cross-platform. A leading ~/ in command/args also works if you prefer that form. I’ll post here when there’s an update.

Cheers for the reply! Does the leading ~ work on Windows? I’ll have to test.

Mike

@douges yes, a leading ~/ works on Windows. In command or an args entry it’s expanded from the OS home directory (the real C:\Users\you\... path), so ~/AppData/Local/Programs/cursor/Cursor.exe resolves correctly, unlike ${userHome} which comes through as the URI form. Two caveats: the ~ has to be at the start of the value, and the expander splits on spaces, so if a path has spaces the ${env:USERPROFILE} form is safer.

thanks mate. testing on windows and macos it works, but it doesn’t work on linux:

2026-09-23 11:22:54.518 [warning] [Shared MCP process] Connection failed: spawn ~/.paper/bin/paper ENOENT
2026-09-23 11:22:54.518 [warning] [Shared MCP process] [V2 FSM] connection:connect_failure: conn=connecting,auth=unknown -> conn=failed,auth=unknown

which is odd because it works fine in terminal:

parallels@ubuntu-gnu-linux-24-04-3:~$ ~/.paper/bin/paper

  ██████████
██     █████
██     █████
███████
███████

Paper CLI
...
parallels@ubuntu-gnu-linux-24-04-3:~$ echo ~/.paper/bin/paper
/home/parallels/.paper/bin/paper

Mike

The ~/ shortcut only gets expanded when a workspace folder is present. Your Linux run went through the shared MCP process (the [Shared MCP process] line in your log), where ~ is passed through literally, so it tried to spawn ~/.paper/bin/paper and failed. So ~/ isn’t reliable across setups. The env-var form is the robust one: use ${env:HOME} on Linux, or your combined ${env:HOME}${env:USERPROFILE}/... which resolves to a real path on every platform. We’ve noted the ~/ gap alongside the original issue so it’s covered too.

Ah okay thanks for the insight, will leave it as is until a fix lands :folded_hands: appreciate the help!

Mike