modelcontextprotocol / modelcontextprotocol/servers
filesystem: recursive search can hang on macOS CloudStorage / lazy provider paths
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 90.5k
- Forks
- 11.7k
- Avg merge
- 2d 2h
- Merged PRs (30d)
- 5
Description
Hi — thanks for maintaining the filesystem server.
I'm filing this against @modelcontextprotocol/server-filesystem after several weeks of production use on macOS with provider-backed directories in allowedDirectories,
especially:
~/Library/CloudStorage/GoogleDrive-.../...~/Library/Mobile Documents/com~apple~CloudDocs/...
Symptom
When allowedDirectories includes macOS CloudStorage / lazy provider paths, search_files and other operations that call validatePath() can intermittently hang for minutes.
Claude Desktop eventually reports the MCP server as unresponsive after roughly 4 minutes. The subprocess remains alive, but subsequent filesystem calls may continue to hang until
the server is restarted.
This may overlap with reports like #3281, but I'm filing separately because this issue points to specific filesystem code paths.
Code paths
In src/filesystem/lib.ts, validatePath() calls:
const realPath = await fs.realpath(absolute);
and, in the ENOENT branch:
const realParentPath = await fs.realpath(parentDir);
These calls have no timeout. On macOS provider-backed paths that are not locally materialized, realpath can block while the provider fetches metadata.
searchFilesWithValidation() then recursively does:
const entries = await fs.readdir(currentPath, { withFileTypes: true });
...
await validatePath(fullPath);
...
if (entry.isDirectory()) {
await search(fullPath);
}
As far as I can tell, recursive search currently has no upper bound on visited entries, no timeout around readdir, and no abort path. A large or lazy-materialized tree can
therefore keep the server busy for a long time.
Why this matters
This is especially visible with CloudStorage / FileProvider-backed folders such as Google Drive and iCloud Drive, where metadata for subdirectories may be fetched lazily. It can
also affect very large local trees.
The libuv threadpool angle may make the symptom worse: filesystem operations use libuv's threadpool, whose default size is 4. A small number of slow filesystem calls can
therefore degrade unrelated filesystem operations in the same process. I mention this as a contributing factor, not necessarily as the main fix.
Suggested mitigations
The two minimal mitigations I'd suggest are:
-
Add a timeout wrapper around
fs.realpathinvalidatePath()and aroundfs.readdirin recursive search. -
Add a configurable maximum visited-entry count for
search_files, returning a clear error such as:Search aborted after visiting N entries. Please refine the pattern or narrow the search path.
Optional follow-ups:
- Document how to exclude / avoid recursive search over CloudStorage-style folders.
- Consider an opt-in exclude-prefix configuration for recursive search.
- Document
UV_THREADPOOL_SIZEtuning for users who intentionally expose large / slow provider-backed trees.
I have tested equivalent mitigations locally in a patched installed build for several weeks with Google Drive and iCloud Drive paths in allowedDirectories. I'm not opening a PR
because the exact configuration surface — env vars vs config object, defaults, and docs placement — seems like a maintainer policy decision, but I'd be happy to test any
proposed fix.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start in src/filesystem/lib.ts by tracing validatePath() and searchFilesWithValidation(), focusing on the fs.realpath and fs.readdir calls described in the issue. Reproduce with a CloudStorage or other lazy provider path and inspect how recursive search handles slow operations. Done should be a clear, bounded failure instead of an unresponsive server, with the chosen configuration surface and defaults documented.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- backend
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100