Summary
The secure-filesystem-server package (src/filesystem/) terminates the Node process during startup if any path passed in allowed_directories is missing or inaccessible. The exit produces no stderr output, no JSON-RPC error response, and no log line indicating which path was the culprit — only the host (Claude Desktop, in my case) sees an abrupt transport close.
This is a sharp edge for end users: any folder rename, drive disconnect, or stale config entry takes the entire connector offline with no diagnostic to act on.
Environment
- Host: Claude Desktop (Windows UWP, but the bug is in the server itself and is host-agnostic)
- OS: Windows 11
- Filesystem connector extension ID:
ant.dir.ant.anthropic.filesystem
- MCP server build: ships with current Claude Desktop (Node-based,
secure-filesystem-server v0.2.0, per server log line "serverInfo":{"name":"secure-filesystem-server","version":"0.2.0"})
Reproduction
-
Configure the filesystem MCP server with an allowed_directories list that contains at least one path which does not exist on disk. For example:
{
"allowed_directories": [
"C:\\PKM",
"C:\\Dev",
"C:\\DevBackup"
]
}
where C:\PKM and C:\Dev exist but C:\DevBackup has been renamed or deleted.
-
Launch the host so the MCP server is spawned.
-
Observe that the server starts, accepts the initialize handshake, and then exits within 1–2 seconds. No tools/list is ever served.
Expected behaviour
One of:
- Preferred: the server starts successfully using the valid subset of
allowed_directories, emits a structured warning (stderr or JSON-RPC notifications/message) naming each invalid path, and continues serving requests scoped to the surviving paths.
- Acceptable: the server fails fast but writes a clear stderr line identifying the offending path, e.g.
Allowed directory does not exist: C:\DevBackup — startup aborted, and exits with a non-zero code that the host can surface.
Either makes the failure actionable.
Actual behaviour
The server exits with no stderr output and no JSON-RPC error. From the host's perspective the connector simply disappears mid-handshake.
Verbatim from %APPDATA%\Claude\logs\mcp-server-Filesystem.log (timestamps trimmed):
[Filesystem] [info] Initializing server...
[Filesystem] [info] Using built-in Node.js for MCP server: Filesystem
[Filesystem] [info] Server started and connected successfully
[Filesystem] [info] Message from client: {"method":"initialize", ... "id":0}
[Filesystem] [info] Server transport closed
[Filesystem] [info] Server transport closed unexpectedly, this is likely due to the process exiting early.
If you are developing this MCP server you can add output to stderr ... and it will appear in this log.
[Filesystem] [error] Server disconnected.
The host UI surfaces three opaque toasts: "MCP Filesystem: Server disconnected", "This isn't working right now", "Could not attach to MCP server Filesystem". None mention which path is bad, which makes the issue hard to diagnose without reading server source.
Suspected root cause
During startup the server resolves every entry in allowed_directories via something equivalent to fs.realpathSync(path) to canonicalise it for later path-prefix checks. When a path is missing this throws ENOENT. The throw is not caught at the validation site, so it propagates to top-level and Node terminates with no handler logging it.
Suggested fix
Wrap per-path validation in try/catch and partition the input into "valid" and "invalid" buckets. Pseudocode:
const valid: string[] = [];
const invalid: { path: string; reason: string }[] = [];
for (const raw of allowedDirectories) {
try {
const resolved = fs.realpathSync(raw);
const stat = fs.statSync(resolved);
if (!stat.isDirectory()) {
invalid.push({ path: raw, reason: 'not a directory' });
continue;
}
valid.push(resolved);
} catch (err: any) {
invalid.push({ path: raw, reason: err?.code ?? err?.message ?? 'unknown' });
}
}
for (const { path, reason } of invalid) {
console.error(`[filesystem] Skipping allowed directory "${path}": ${reason}`);
}
if (valid.length === 0) {
console.error('[filesystem] No valid allowed directories — aborting.');
process.exit(1);
}
// continue startup with `valid`
This:
- Names every bad path on stderr, which the host displays in its server log.
- Keeps the connector alive for the valid subset (matches user intent in the common case where only one of several drives is offline).
- Aborts cleanly with a clear message if every path is bad.
An optional follow-up would be to emit a notifications/message MCP event after initialize so the host can render an inline warning in its UI, but the stderr line alone already unlocks 95% of the diagnostic value.
Impact
This silent-failure mode wastes substantial debugging time. In my case I'd renamed a folder hours earlier and forgotten it was in the connector list; the toasts gave no indication that a path was the problem, so I spent ~30 minutes reading mcp.log, main.log, and the Filesystem server log before finally diffing the allowed_directories JSON against the actual filesystem.
I've also filed a corresponding feedback note with Anthropic about the Claude Desktop side of the UX (better host-side dialog when a connector fails). This issue covers only the upstream server-side change.
Additional notes
- The same code path may affect other Node-based MCP servers in this repo that take a directory list as a startup argument — worth checking, though I haven't reproduced there.
- Happy to test a candidate fix on Windows + Claude Desktop UWP and confirm the new behaviour if a PR lands.
Summary
The
secure-filesystem-serverpackage (src/filesystem/) terminates the Node process during startup if any path passed inallowed_directoriesis missing or inaccessible. The exit produces no stderr output, no JSON-RPC error response, and no log line indicating which path was the culprit — only the host (Claude Desktop, in my case) sees an abrupt transport close.This is a sharp edge for end users: any folder rename, drive disconnect, or stale config entry takes the entire connector offline with no diagnostic to act on.
Environment
ant.dir.ant.anthropic.filesystemsecure-filesystem-serverv0.2.0, per server log line"serverInfo":{"name":"secure-filesystem-server","version":"0.2.0"})Reproduction
Configure the filesystem MCP server with an
allowed_directorieslist that contains at least one path which does not exist on disk. For example:{ "allowed_directories": [ "C:\\PKM", "C:\\Dev", "C:\\DevBackup" ] }where
C:\PKMandC:\Devexist butC:\DevBackuphas been renamed or deleted.Launch the host so the MCP server is spawned.
Observe that the server starts, accepts the
initializehandshake, and then exits within 1–2 seconds. Notools/listis ever served.Expected behaviour
One of:
allowed_directories, emits a structured warning (stderr or JSON-RPCnotifications/message) naming each invalid path, and continues serving requests scoped to the surviving paths.Allowed directory does not exist: C:\DevBackup — startup aborted, and exits with a non-zero code that the host can surface.Either makes the failure actionable.
Actual behaviour
The server exits with no stderr output and no JSON-RPC error. From the host's perspective the connector simply disappears mid-handshake.
Verbatim from
%APPDATA%\Claude\logs\mcp-server-Filesystem.log(timestamps trimmed):The host UI surfaces three opaque toasts: "MCP Filesystem: Server disconnected", "This isn't working right now", "Could not attach to MCP server Filesystem". None mention which path is bad, which makes the issue hard to diagnose without reading server source.
Suspected root cause
During startup the server resolves every entry in
allowed_directoriesvia something equivalent tofs.realpathSync(path)to canonicalise it for later path-prefix checks. When a path is missing this throwsENOENT. The throw is not caught at the validation site, so it propagates to top-level and Node terminates with no handler logging it.Suggested fix
Wrap per-path validation in try/catch and partition the input into "valid" and "invalid" buckets. Pseudocode:
This:
An optional follow-up would be to emit a
notifications/messageMCP event afterinitializeso the host can render an inline warning in its UI, but the stderr line alone already unlocks 95% of the diagnostic value.Impact
This silent-failure mode wastes substantial debugging time. In my case I'd renamed a folder hours earlier and forgotten it was in the connector list; the toasts gave no indication that a path was the problem, so I spent ~30 minutes reading
mcp.log,main.log, and the Filesystem server log before finally diffing theallowed_directoriesJSON against the actual filesystem.I've also filed a corresponding feedback note with Anthropic about the Claude Desktop side of the UX (better host-side dialog when a connector fails). This issue covers only the upstream server-side change.
Additional notes