DXT ${__dirname} resolves to MSIX-virtualized path, breaking external process spawns
Summary
When Claude Desktop is installed as an MSIX package on Windows, DXT extensions that spawn external processes (e.g. py.exe for Python MCP servers) fail because ${__dirname} resolves to a path inside the MSIX virtual filesystem that external processes cannot see.
Environment
- Windows 11 Pro
- Claude Desktop (MSIX-packaged,
Claude_pzs8sxrjxfjjc) - DXT extension with
type: "python"using${__dirname}inmcp_config.args
Steps to Reproduce
- Install Claude Desktop on a fresh Windows machine (no prior Claude Desktop installation)
- Install a DXT extension (
.mcpb) that uses a Python MCP server with this manifest:
``json``
"server": {
"type": "python",
"entry_point": "server.py",
"mcp_config": {
"command": "py",
"args": ["${__dirname}/server.py"]
}
}
- Claude Desktop extracts the bundle and spawns
py.exewith the resolved${__dirname}path
Expected Behavior
py.exe finds and runs server.py at the path provided by ${__dirname}.
Actual Behavior
C:\Program Files\Python312\python.exe: can't open file
'C:\Users\<user>\AppData\Roaming\Claude\Claude Extensions\<extension-id>/server.py':
[Errno 2] No such file or directory
The file actually exists at the MSIX-virtualized path:
C:\Users\<user>\AppData\Local\Packages\Claude_pzs8sxrjxfjjc\LocalCache\Roaming\Claude\Claude Extensions\<extension-id>\server.py
Root Cause
MSIX filesystem virtualization redirects AppData\Roaming\ writes to AppData\Local\Packages\Claude_pzs8sxrjxfjjc\LocalCache\Roaming\. Claude Desktop (inside the sandbox) resolves ${__dirname} to the virtual path (AppData\Roaming\...), but the spawned external process (py.exe) runs outside the MSIX sandbox and cannot see files at that path.
Per Microsoft's MSIX docs, on Windows 10 1903+:
- Newly created files/folders in AppData are written to the per-app virtualized location
- Child processes spawned by MSIX apps do not inherit the package context
- Command-line argument paths are not automatically rewritten from virtual to real paths
This only affects fresh installations where Claude Extensions\ didn't previously exist at the real AppData\Roaming\ path. Machines with a pre-existing folder (from an earlier non-MSIX install) are unaffected because MSIX writes to pre-existing real paths.
Workaround
Manually create the real directory before installing the extension, so MSIX doesn't virtualize it:
New-Item -ItemType Directory -Path "$env:APPDATA\Claude\Claude Extensions" -Force
Then reinstall the .mcpb extension.
Suggested Fix
When resolving ${__dirname}, Claude Desktop should detect MSIX packaging and resolve to the real filesystem path (AppData\Local\Packages\...\LocalCache\Roaming\...) rather than the virtual path, since spawned child processes run outside the sandbox.
Alternatively, Claude Desktop could write extensions to a non-AppData location (MSIX only virtualizes AppData paths), or declare unvirtualizedResources / FilesystemWriteVirtualization=disabled in its MSIX manifest for the extensions directory.
Related Issues
- #25579 — MSIX virtualization redirects
app.getPath("userData"); documents the core path mismatch - #26073 — "Edit Config" opens wrong
claude_desktop_config.jsondue to MSIX path - #29302 — Windows-MCP extension fails because executable in MSIX virtualized path is blocked
- #35037 — MSIX causes
rename()EXDEV errors crossing virtual/real boundary
This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗