fix(filesystem): preserve CLI directories when merging with MCP roots - #3612
fix(filesystem): preserve CLI directories when merging with MCP roots#3612Bingtagui404 wants to merge 5 commits into
Conversation
The oninitialized and roots/list_changed handlers replaced all CLI-provided allowed directories with client roots, silently discarding any extra directories passed via command-line arguments. Store CLI directories as an immutable baseline and merge them with client roots using a Set for deduplication. When roots become empty or invalid, fall back to the CLI baseline instead of keeping stale roots. Fixes modelcontextprotocol#3602
4127473 to
a4a0032
Compare
|
Filesystem checks are passing for this PR. The only failing job is |
|
Filesystem-related checks are passing for this PR. The failing |
|
To clarify: the |
|
@claude review |
|
Claude finished @cliffhall's task in 1m 45s —— View job PR Review
SummaryThis PR correctly fixes a real bug: when a client sends roots via the MCP protocol, the server was unconditionally replacing CLI-provided Verdict: Looks good overall with one stale comment to fix (minor). What changed (diff summary)
Issue foundStale comment at That describes the old behavior. The new behavior merges CLI dirs with the incoming roots rather than replacing. The comment should be updated to reflect that. Fix this → Correctness analysis
allowedDirectories = accessibleDirectories; // line 90 — filtered to accessible only
const cliAllowedDirectories = [...allowedDirectories]; // line 95 — snapshot taken hereCaptured after accessibility filtering, so inaccessible CLI dirs aren't re-admitted through the merge path. Correct.
return [...new Set([...cliAllowedDirectories, ...rootDirectories])];Simple, correct, and preserves CLI-first ordering (CLI dirs appear before root dirs in the result). The Empty-roots fallback behavior
Symlink handling
TestsThe three new tests cover exactly the three contract properties of
All tests operate on the pure helper function rather than the full server setup, which is appropriate since the mutation logic in Minor notes (non-blocking)
Overall this is a clean, minimal fix with good test coverage. The only actionable item before merge is updating the stale comment at line 724. |
LuuOW
left a comment
There was a problem hiding this comment.
Technical audit: Verified MCP server implementation for consistency with current SDK patterns.
Summary
Fixes #3602
When the MCP client supports the roots protocol, the
oninitializedandroots/list_changedhandlers unconditionally replaced all CLI-providedallowedDirectorieswith client roots. This caused any extra directories passed via command-line arguments to be silently discarded.Before:
npx @modelcontextprotocol/server-filesystem /home/user /mnt/Storage /mnt/Games+ client root/home/user→ only/home/useraccessible.After: CLI directories are preserved as an immutable baseline and merged with client roots. All four directories remain accessible.
Changes
src/filesystem/index.ts: Save CLI directories ascliAllowedDirectoriesbaseline. ChangeupdateAllowedDirectoriesFromRootsto merge CLI baseline + current client roots instead of replacing. When roots become empty/invalid, fall back to CLI baseline only (no stale roots).src/filesystem/roots-utils.ts: AddmergeAllowedDirectories()helper — usesSetto deduplicate CLI dirs + root dirs.src/filesystem/__tests__/roots-utils.test.ts: Add 3 regression tests:Test plan
npx tsc --noEmit— type check passesnpx vitest run --config src/filesystem/vitest.config.ts src/filesystem/__tests__/roots-utils.test.ts— all 6 tests pass (3 existing + 3 new)