Skip to content

fix(filesystem): respect CLI directories when client supports MCP roots#3938

Open
ssam18 wants to merge 1 commit intomodelcontextprotocol:mainfrom
ssam18:fix/filesystem-cli-dirs-override
Open

fix(filesystem): respect CLI directories when client supports MCP roots#3938
ssam18 wants to merge 1 commit intomodelcontextprotocol:mainfrom
ssam18:fix/filesystem-cli-dirs-override

Conversation

@ssam18
Copy link
Copy Markdown

@ssam18 ssam18 commented Apr 13, 2026

When a client advertises roots support, the server was unconditionally replacing CLI-provided directories with whatever the client returned, making it impossible to scope the server to a directory outside the project root.

The fix tracks whether directories were passed via CLI args at startup and skips the roots fetch in both the oninitialized handler and the roots/list_changed notification handler when they were. MCP roots now only kick in as a fallback when no CLI args are given. Fixes #3929

@cliffhall cliffhall added bug Something isn't working server-filesystem Reference implementation for the Filesystem MCP server - src/filesystem labels Apr 20, 2026
@cliffhall
Copy link
Copy Markdown
Member

@claude review

@claude
Copy link
Copy Markdown
Contributor

claude Bot commented Apr 21, 2026

Claude finished @cliffhall's task in 1m 47s —— View job


PR Review

  • Gather context
  • Read changed files
  • Analyze implementation logic
  • Post review feedback

The fix is correct and minimal — only 7 lines changed across three logical locations. The approach of capturing cliDirectoriesProvided at startup and using it as a guard in both the oninitialized handler and the roots/list_changed notification handler is sound. Here are my findings:

What works well

  • Tight scope: The single boolean flag is set once, in the right place (after raw args parsing), and used in exactly the two spots where roots can override directories.
  • Safety: Even though cliDirectoriesProvided checks raw args.length before accessibility filtering, there's no risk of a hole — the server calls process.exit(1) at line 86–89 when all CLI dirs are inaccessible, so oninitialized is never reached in that case.
  • Removal of the now-redundant comment on the listRoots() call in the notification handler is a clean housekeeping win.

Issues

1. Misleading log message in the else branch (minor bug)

src/filesystem/index.ts:748–754

} else {
  if (allowedDirectories.length > 0) {
    console.error("Client does not support MCP Roots, using allowed directories set from server args:", allowedDirectories);
  } else {
    throw new Error(`Server cannot operate: No allowed directories available...`);
  }
}

The else branch is now reached in two distinct situations:

  1. Client genuinely doesn't support MCP roots.
  2. Client supports roots, but CLI dirs were provided so the server intentionally ignores them.

The log message "Client does not support MCP Roots…" is wrong in case 2. Anyone debugging why the server isn't picking up the client's roots will be confused by the false claim. The fix should add a separate log path:

} else {
  if (cliDirectoriesProvided) {
    console.error("CLI directories provided — ignoring client MCP roots:", allowedDirectories);
  } else if (allowedDirectories.length > 0) {
    console.error("Client does not support MCP Roots, using allowed directories set from server args:", allowedDirectories);
  } else {
    throw new Error(`Server cannot operate: ...`);
  }
}

Fix this →

2. No test coverage for the new behavior

The existing suite (startup-validation.test.ts) spawns the real server binary and tests startup edge cases. The new behavior — "server keeps CLI dirs when client sends roots" — isn't exercised anywhere. Adding even a single test would catch regressions. A high-level sketch:

it('should keep CLI directories when client sends roots/list_changed', async () => {
  // Start server with a CLI dir, perform MCP init with roots capability,
  // send roots/list_changed with a different dir, assert allowed dirs unchanged
});

This is more involved (requires MCP handshake simulation), but there's a precedent in the test file structure for integration-style tests. Worth considering for a follow-up.

Summary

The core logic is correct and the fix addresses the bug. The only meaningful issue is the misleading log message in the else branch — it's a one-liner to fix and would materially help anyone troubleshooting. Test coverage is a nice-to-have rather than a blocker.

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.

MCP roots protocol overrides CLI-provided allowed directories

2 participants