Skip to content

WSL Integration

Unified WSL/Windows file integration in a single tool Version: v4.5.29 | Last updated: 2026-07-11

Repo: https://github.com/scopweb/mcp-filesystem-go-ultra


  1. What changed in v4.x?
  2. The unified wsl tool
  3. Actions at a glance
  4. Cross-platform path conversion
  5. Auto-sync via MCP_WSL_AUTOSYNC (v3.x legacy)
  6. Allowed-paths and security
  7. Common workflows
  8. Troubleshooting

In v3 (≤ 3.13.2) the WSL surface was a fleet of separate tools: wsl_sync, wsl_status, configure_autosync, autosync_status, wsl_to_windows_copy, windows_to_wsl_copy, sync_claude_workspace, and wsl_windows_status. Most were removed during the v4.0.0 consolidation.

In v4.5.x the entire surface lives under one tool: wsl. Four actions cover every use case, and path conversion is automatic in every read/write/edit tool (you rarely need to call wsl at all — see Cross-platform path conversion).

v3.x toolv4.5.x replacement
wsl_statuswsl(action:"status")
wsl_syncwsl(action:"sync", ...)
configure_autosyncwsl(action:"autosync_config", enabled:...)
autosync_statuswsl(action:"autosync_status")
wsl_to_windows_copywsl(action:"sync") w/ wsl_path+windows_path
windows_to_wsl_copywsl(action:"sync") w/ windows_path+wsl_path
sync_claude_workspacewsl(action:"sync", direction:..., filter_pattern:...)

The wsl tool is the single entry point for everything related to WSL/Windows integration. It accepts an action parameter that selects one of four modes:

// Compact discovery — list the actions:
help() // full tool catalog

The four actions (see tools_platform.go for the live source):

actionPurpose
sync (default)Workspace sync OR single-file copy WSL↔Windows
statusEnvironment + paths + directory status report
autosync_configEnable / disable auto-sync on writes and edits
autosync_statusRead the current auto-sync config + whether it is active

The handler validates both source and destination paths against --allowed-paths after conversion, so a caller cannot bridge a write through a denied directory.


1. wsl(action:"sync") — workspace sync or single-file copy

Section titled “1. wsl(action:"sync") — workspace sync or single-file copy”

sync has two modes selected by the parameters supplied:

wsl({
action: "sync",
direction: "wsl_to_windows", // wsl_to_windows | windows_to_wsl | bidirectional
filter_pattern: "*.go", // optional glob
create_dirs: true, // default true
dry_run: false // preview without writing
})

Compact response: OK: 12 files synced, 0 errors

Verbose response lists every synced file and any per-file error (capped at 10 errors to keep responses bounded).

Single-file copy (when wsl_path or windows_path is set)

Section titled “Single-file copy (when wsl_path or windows_path is set)”
// WSL → Windows (auto-computes Windows path from wsl_path if missing)
wsl({
action: "sync",
wsl_path: "/home/user/app.go"
})
// Windows → WSL
wsl({
action: "sync",
windows_path: "C:\\Users\\user\\app.go",
wsl_path: "/home/user/app.go" // optional — auto-computed if omitted
})

Compact response: OK: Copied to C:\Users\user\app.go

The TOCTOU defense runs before every copy — both source and destination are re-resolved via engine.ResolveAndAuthorize so a symlink cannot redirect the copy outside --allowed-paths.

2. wsl(action:"status") — environment report

Section titled “2. wsl(action:"status") — environment report”
wsl({ action: "status" })

Returns:

  • Environment (windows, wsl, linux)
  • Running in WSL: true/false
  • Windows User (when detected)
  • WSL home + Windows home in both styles
  • Path separator, Windows interop availability
  • A Directory Status block listing whether each known directory exists

Compact: Env: wsl, WSL: true

3. wsl(action:"autosync_config", enabled:bool, ...)

Section titled “3. wsl(action:"autosync_config", enabled:bool, ...)”

Enable or disable auto-sync. Other knobs:

  • sync_on_write (default true)
  • sync_on_edit (default true)
  • silent (default false)
wsl({ action: "autosync_config", enabled: true, silent: true })

If the server is not running inside WSL, enabling auto-sync returns a warning that the feature will be inert.

Read-only report of the active auto-sync config:

Auto-Sync Status
---
Status: ENABLED
Environment: WSL
Sync on Write: true
Sync on Edit: true
Sync on Delete: false
Config File: /home/user/.config/mcp-filesystem-ultra/autosync.json

wsl is the explicit tool, but every filesystem tool in v4.5.x auto-converts paths. You almost never need to call wsl for routine editing — read_file, edit_file, multi_edit, write_file, delete_file, search_files, etc., all call core.NormalizePath on the input before any I/O.

The conversion matrix (core/path_converter.go):

You pass (inside WSL)Resolves to (on disk)
/home/user/app.go/home/user/app.go (no conversion)
/mnt/c/Users/user/app.goC:\Users\user\app.go
C:\Users\user\app.go/mnt/c/Users/user/app.go
You pass (native Windows)Resolves to (on disk)
C:\Users\user\app.goC:\Users\user\app.go
/mnt/c/Users/user/app.goC:\Users\user\app.go
/home/user/app.go\\wsl$\Ubuntu\home\user\app.go (best-effort)

The two helpers used everywhere are core.WSLToWindows and core.WindowsToWSL. They are exported and can be used by the engine directly. Path conversion respects --allowed-paths — a path that converts into a denied location is rejected with access denied.

wsl({ action: "status" })
// → look for "Windows Home (WSL style)" and "Windows Home (Windows style)"

If both are populated, conversion is wired correctly.


Auto-sync via MCP_WSL_AUTOSYNC (v3.x legacy)

Section titled “Auto-sync via MCP_WSL_AUTOSYNC (v3.x legacy)”

The MCP_WSL_AUTOSYNC=true environment variable from v3.x still works in v4.5.x as a one-liner enable for auto-sync. The mechanism:

  1. Engine startup reads MCP_WSL_AUTOSYNC.
  2. If set to true, auto-sync is enabled with the config-file defaults.
  3. wsl(action:"autosync_config") overrides whatever the env var set.
Terminal window
# v3.x one-liner still works:
export MCP_WSL_AUTOSYNC=true
filesystem-ultra-v4 --allowed-paths=/home/user/projects

For anything beyond “just turn it on”, prefer the explicit config file or the autosync_config action — they survive env-var loss (process restart without the export) and let you tune sync_on_write / silent / etc.

The config file location (unchanged from v3.4): ~/.config/mcp-filesystem-ultra/autosync.json. See core/autosync_config.go for the schema.


Every wsl call validates both sides of the conversion against --allowed-paths. The conversion runs first, then the check. Implications:

  • If --allowed-paths is empty, all paths are allowed (default).
  • If --allowed-paths=/home/user/projects, a wsl copy that resolves to /tmp/foo.go is rejected with access denied: one or both paths are outside allowed directories.
  • Symlinks pointing outside the allowed set are caught by core.ResolveSymlinks — the resolved canonical path is checked, not the user-supplied path (TOCTOU defense).

This is a hardening introduced in v4.5.5 (the “WSL / Auto-sync security” release). Earlier versions did not validate target paths.


// One-time: enable auto-sync with silent mode
wsl({ action: "autosync_config", enabled: true, silent: true })
// From this point, every write_file / edit_file / multi_edit on a WSL path
// is silently mirrored to its Windows location. No manual sync needed.
wsl({
action: "sync",
windows_path: "C:\\Users\\user\\Downloads\\data.json",
wsl_path: "/home/user/projects/data.json"
})
// → "OK: Copied to /home/user/projects/data.json"
wsl({
action: "sync",
direction: "wsl_to_windows",
filter_pattern: "*.go",
dry_run: true
})
// → "Workspace Sync Results ... Mode: DRY RUN (preview only)"

“access denied: one or both paths are outside allowed directories”

Section titled ““access denied: one or both paths are outside allowed directories””

--allowed-paths rejected one of the converted paths. Either pass /home/user (or your workspace root) as an allowed path, or adjust the source/destination to stay inside the existing allowed set.

  1. Confirm the server is actually running inside WSL (wsl(action:"status")).
  2. Confirm auto-sync is enabled (wsl(action:"autosync_status")).
  3. Confirm the file is in a path under --allowed-paths.
  4. If silent: true, there are no logs to grep — temporarily flip to silent: false and watch stderr for [AutoSync] lines.

The env var is read once at startup. Set it before launching filesystem-ultra-v4. After startup, change config with wsl(action:"autosync_config").

The Windows path differs from what I expected

Section titled “The Windows path differs from what I expected”

/mnt/c/... and C:\... are interchangeable. The engine normalises them to the same canonical form before any I/O. If you see different resolved paths, you are looking at a case sensitivity issue (Windows is case-insensitive; the engine preserves the path you gave it on the way out for display). Always copy paths from list_directory or read_file output — never retype from memory.



Version: 4.5.29 Last updated: 2026-07-11