Skip to content

fix(filesystem): normalize path separators in search_files results#3965

Open
ianliuy wants to merge 1 commit intomodelcontextprotocol:mainfrom
ianliuy:fix/issue-3517
Open

fix(filesystem): normalize path separators in search_files results#3965
ianliuy wants to merge 1 commit intomodelcontextprotocol:mainfrom
ianliuy:fix/issue-3517

Conversation

@ianliuy
Copy link
Copy Markdown

@ianliuy ianliuy commented Apr 16, 2026

What's broken?

The filesystem server's search_files tool and directory_tree exclude patterns return inconsistent results across platforms. On Windows, glob patterns like **/*.ts fail to match because paths use backslashes internally.

Who is affected?

Anyone using the filesystem MCP server on Windows. Linux/macOS users are unaffected since path.sep is already /.

When does it trigger?

Every time search_files or directory_tree (with exclude patterns) is called on Windows. The glob patterns silently fail to match, returning incorrect results.

Where is the bug?

  • src/filesystem/lib.tssearchFilesWithValidation(), line computing relativePath
  • src/filesystem/index.tsbuildTree(), line computing relativePath

Both use path.relative() which returns backslash-separated paths on Windows (e.g., src\index.ts), then pass them directly to minimatch which expects forward slashes.

Why does it happen?

path.relative() uses the OS-native separator (\ on Windows, / on Linux). minimatch is a glob library that operates on forward-slash paths. When backslash paths are passed to minimatch on Windows, patterns like **/*.ts don't match src\index.ts.

How did we fix it?

Normalize relativePath to forward slashes immediately after computing it:

// Before
const relativePath = path.relative(rootPath, fullPath);

// After
const relativePath = path.relative(rootPath, fullPath).split(path.sep).join('/');

This is applied in both locations. The fix is minimal (2 lines changed) and only affects the path format used for glob matching — the returned full paths from search_files remain OS-native.

How do we know it works?

All 57 related tests pass (lib.test.ts, directory-tree.test.ts, structured-content.test.ts including the search_files test). The .split(path.sep).join('/') pattern is a no-op on Linux/macOS (where path.sep is already /), so there's zero risk of regression on those platforms.

Fixes #3517

On Windows, path.relative() returns backslash-separated paths (e.g.,
src\index.ts), but minimatch expects forward slashes for glob pattern
matching (e.g., **/*.ts). This causes search_files and directory_tree
exclude patterns to fail on Windows.

Fix by normalizing relativePath to use forward slashes via
.split(path.sep).join('/') before passing to minimatch in both
searchFilesWithValidation (lib.ts) and buildTree (index.ts).

Fixes modelcontextprotocol#3517

Co-authored-by: Copilot <[email protected]>
Signed-off-by: Yiyang Liu <[email protected]>
@cliffhall cliffhall added bug Something isn't working server-filesystem Reference implementation for the Filesystem MCP server - src/filesystem labels Apr 20, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working server-filesystem Reference implementation for the Filesystem MCP server - src/filesystem

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Filesystem server glob pattern matching inconsistent across platforms

2 participants