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 <223556219+Copilot@users.noreply.github.com>
Signed-off-by: Yiyang Liu <37043548+ianliuy@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

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

1 participant