Skip to content

fix(filesystem): handle paths containing tilde (~) without crashing#3595

Open
VoidChecksum wants to merge 1 commit intomodelcontextprotocol:mainfrom
VoidChecksum:fix/filesystem-tilde-path-expansion
Open

fix(filesystem): handle paths containing tilde (~) without crashing#3595
VoidChecksum wants to merge 1 commit intomodelcontextprotocol:mainfrom
VoidChecksum:fix/filesystem-tilde-path-expansion

Conversation

@VoidChecksum
Copy link

Summary

Fixes #3412 — the filesystem MCP server crashes silently when configured directories contain tilde (~) characters in their names.

Root causes identified and fixed:

  • Malformed file:// URIs: When a path like ~/folder is naively concatenated as file://~/folder, the URL parser interprets ~ as the hostname, causing fileURLToPath() to throw. Added safeFileURLToPath() that recovers from this by extracting and decoding the path component.

  • Silent error swallowing: parseRootUri() caught all errors and returned null with no logging. When all roots failed validation, the server continued with zero allowed directories and no indication of what went wrong. Now logs descriptive warnings for each failed root.

  • Unhandled promise rejection crash: The oninitialized handler threw an Error inside an async callback when no directories were available. This caused an unhandled promise rejection that crashed the Node.js process silently. Replaced with console.error() + process.exit(1) for a clean exit with a descriptive message.

  • Duplicated tilde expansion logic: parseRootUri() had its own inline tilde expansion instead of using the shared expandHome() function. Consolidated to use the shared function for consistent behavior.

Additional improvements:

  • Added warning when all client-provided roots fail validation, listing the URIs that failed
  • Improved expandHome() documentation to clarify handling of literal ~ in directory names vs home directory shorthand

Changes

File Change
roots-utils.ts Add safeFileURLToPath(), use shared expandHome(), add error logging
index.ts Replace throw with process.exit(1), add root validation warning
path-utils.ts Improve expandHome() documentation
__tests__/roots-utils.test.ts 4 new tests for tilde path handling
__tests__/path-utils.test.ts 3 new tests for tilde in expandHome()
__tests__/lib.test.ts 2 new tests for validatePath() with tilde paths

Test plan

  • All 154 tests pass (145 existing + 9 new)
  • Directories with literal ~ in name resolve correctly via file URI
  • Directories with literal ~ in name resolve correctly via plain path
  • Malformed file://~/path URIs are handled gracefully (not crash)
  • Multiple tilde-containing directories work simultaneously
  • validatePath accepts paths with ~ in directory names
  • Home expansion (~/) combined with literal ~ in subdirectory names works
  • Windows short names with tilde (PROGRA~1) are preserved
  • Server logs descriptive errors instead of crashing silently

Generated with Claude Code

Fix silent server crashes when configured directories contain tilde
characters, addressing both the crash mechanism and root cause.

Changes:
- Add safeFileURLToPath() to handle malformed file:// URIs where tilde
  in the path gets misinterpreted as the URI authority component
  (e.g. file://~/path treats ~ as hostname, causing fileURLToPath to throw)
- Replace inline tilde expansion in parseRootUri with shared expandHome()
  to ensure consistent behavior across all code paths
- Add descriptive error logging in parseRootUri instead of silently
  returning null, so users can diagnose path resolution failures
- Replace unhandled throw in oninitialized with console.error + process.exit
  to prevent silent crashes from unhandled promise rejections
- Add warning when all client-provided roots fail validation, listing the
  URIs that failed so users can identify the problematic paths
- Improve expandHome documentation to clarify tilde handling semantics

Tests added:
- Directories with literal tilde in name via file URI and plain path
- Malformed file://~/path URIs (tilde in authority position)
- Multiple directories with tildes
- validatePath with tilde in directory names
- Home expansion combined with literal tilde in subdirectory names
- Windows short names with tilde (PROGRA~1)

Closes modelcontextprotocol#3412
Copilot AI review requested due to automatic review settings March 15, 2026 19:52
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes a crash in the filesystem MCP server when configured roots include ~ (either as home shorthand or as a literal character) by hardening root URI/path parsing, improving diagnostics, and adding regression tests.

Changes:

  • Add safeFileURLToPath() and update root parsing to handle malformed file:// URIs and use shared expandHome().
  • Improve initialization-time diagnostics and exit behavior when no allowed directories can be established.
  • Expand expandHome() documentation and add tests covering tilde-related scenarios.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
src/filesystem/roots-utils.ts Adds safer file-URI conversion, consolidates tilde expansion via expandHome(), and logs root-resolution failures.
src/filesystem/path-utils.ts Clarifies expandHome() behavior for literal ~ vs home shorthand.
src/filesystem/index.ts Adds warning when all client roots fail validation; exits cleanly when no directories are available.
src/filesystem/__tests__/roots-utils.test.ts Adds coverage for literal-tilde directory names and malformed file://~/... URIs.
src/filesystem/__tests__/path-utils.test.ts Adds coverage for literal ~ segments and Windows short-name tildes.
src/filesystem/__tests__/lib.test.ts Adds coverage ensuring validatePath() accepts literal-tilde paths and ~/.../~dir combinations.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

You can also share your feedback on Copilot code review. Take the survey.

Comment on lines +22 to +31
// Try to recover by extracting the path after "file://" and normalizing it.
try {
const withoutScheme = uri.slice('file://'.length);
// If the path starts with / it's absolute (file:///path or file:///~/path)
if (withoutScheme.startsWith('/')) {
return decodeURIComponent(withoutScheme);
}
// Otherwise treat the whole part after file:// as a path
// (e.g., file://~/folder -> ~/folder)
return decodeURIComponent(withoutScheme);
Comment on lines +64 to +67
} catch (error) {
const message = error instanceof Error ? error.message : String(error);
console.error(`Warning: Could not resolve root path "${rootUri}": ${message}`);
return null;
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.

Filesystem MCP server crashes silently on paths containing ~ (tilde) character

2 participants