When using @modelcontextprotocol/server-filesystem on Windows with UNC paths (e.g. \192.168.1.1\share) as allowed directories, file access always fails with "Access denied - path outside allowed directories" — even for files that are clearly within the allowed path.
Root cause:
In path-validation.js, isPathWithinAllowedDirectories calls path.resolve(path.normalize(absolutePath)) on UNC paths. On Windows, path.normalize can strip one leading backslash from \server\share\file, turning it into \server\share\file. Subsequently, path.resolve interprets this single-backslash path as drive-relative (e.g. C:\server\share\file), causing the allowed-directory check to fail.
Fix:
UNC paths (starting with \) should bypass path.resolve and be compared directly as strings after normalization:
javascriptconst uncPath = absolutePath.startsWith('\\');
if (uncPath && !tempPath.startsWith('\\')) {
normalizedPath = '\' + tempPath; // restore stripped backslash
} else {
normalizedPath = path.resolve(tempPath);
}
Or more robustly, use case-insensitive string comparison for UNC paths entirely.
To reproduce:
Map a network share on Windows: net use Y: \192.168.x.x\share
Add Y:\ or \192.168.x.x\share\ to allowed directories in claude_desktop_config.json
Try to read any file — access is denied despite the file being within the allowed path
Environment: Windows 11, @modelcontextprotocol/server-filesystem (npm global install), Claude Desktop
When using @modelcontextprotocol/server-filesystem on Windows with UNC paths (e.g. \192.168.1.1\share) as allowed directories, file access always fails with "Access denied - path outside allowed directories" — even for files that are clearly within the allowed path.
Root cause:
In path-validation.js, isPathWithinAllowedDirectories calls path.resolve(path.normalize(absolutePath)) on UNC paths. On Windows, path.normalize can strip one leading backslash from \server\share\file, turning it into \server\share\file. Subsequently, path.resolve interprets this single-backslash path as drive-relative (e.g. C:\server\share\file), causing the allowed-directory check to fail.
Fix:
UNC paths (starting with \) should bypass path.resolve and be compared directly as strings after normalization:
javascriptconst uncPath = absolutePath.startsWith('\\');
if (uncPath && !tempPath.startsWith('\\')) {
normalizedPath = '\' + tempPath; // restore stripped backslash
} else {
normalizedPath = path.resolve(tempPath);
}
Or more robustly, use case-insensitive string comparison for UNC paths entirely.
To reproduce:
Map a network share on Windows: net use Y: \192.168.x.x\share
Add Y:\ or \192.168.x.x\share\ to allowed directories in claude_desktop_config.json
Try to read any file — access is denied despite the file being within the allowed path
Environment: Windows 11, @modelcontextprotocol/server-filesystem (npm global install), Claude Desktop