From 7ae389b50659bec9573e4f60633265fd6b3cb610 Mon Sep 17 00:00:00 2001 From: tarunag10 Date: Tue, 2 Jun 2026 11:24:21 +0100 Subject: [PATCH] Improve filesystem startup directory diagnostics --- .../__tests__/startup-validation.test.ts | 14 ++++++++-- src/filesystem/index.ts | 26 +++++++++++++++++-- 2 files changed, 36 insertions(+), 4 deletions(-) diff --git a/src/filesystem/__tests__/startup-validation.test.ts b/src/filesystem/__tests__/startup-validation.test.ts index 3be283df74..fa697c2e42 100644 --- a/src/filesystem/__tests__/startup-validation.test.ts +++ b/src/filesystem/__tests__/startup-validation.test.ts @@ -18,6 +18,9 @@ async function spawnServer(args: string[], timeoutMs = 2000): Promise<{ exitCode let stderr = ''; proc.stderr?.on('data', (data) => { stderr += data.toString(); + if (stderr.includes('Secure MCP Filesystem Server running on stdio')) { + proc.kill('SIGTERM'); + } }); const timeout = setTimeout(() => { @@ -66,8 +69,10 @@ describe('Startup Directory Validation', () => { const result = await spawnServer([nonExistentDir, accessibleDir]); // Should warn about inaccessible directory - expect(result.stderr).toContain('Warning: Cannot access directory'); + expect(result.stderr).toContain('Warning: Skipping invalid allowed directory'); expect(result.stderr).toContain(nonExistentDir); + expect(result.stderr).toContain('ENOENT'); + expect(result.stderr).toContain('no such file or directory'); // Should still start successfully expect(result.stderr).toContain('Secure MCP Filesystem Server running on stdio'); @@ -82,6 +87,10 @@ describe('Startup Directory Validation', () => { // Should exit with error expect(result.exitCode).toBe(1); expect(result.stderr).toContain('Error: None of the specified directories are accessible'); + expect(result.stderr).toContain('Invalid allowed directories:'); + expect(result.stderr).toContain(nonExistent1); + expect(result.stderr).toContain(nonExistent2); + expect(result.stderr).toContain('ENOENT'); }); it('should warn when path is not a directory', async () => { @@ -91,7 +100,8 @@ describe('Startup Directory Validation', () => { const result = await spawnServer([filePath, accessibleDir]); // Should warn about non-directory - expect(result.stderr).toContain('Warning:'); + expect(result.stderr).toContain('Warning: Skipping invalid allowed directory'); + expect(result.stderr).toContain(filePath); expect(result.stderr).toContain('not a directory'); // Should still start with the valid directory diff --git a/src/filesystem/index.ts b/src/filesystem/index.ts index 7b67e63e58..05bd21c08f 100644 --- a/src/filesystem/index.ts +++ b/src/filesystem/index.ts @@ -28,6 +28,19 @@ import { setAllowedDirectories, } from './lib.js'; +type InvalidAllowedDirectory = { + directory: string; + reason: string; +}; + +function formatStartupValidationError(error: unknown): string { + if (error instanceof Error) { + return error.message; + } + + return String(error); +} + // Command line argument parsing const args = process.argv.slice(2); if (args.length === 0) { @@ -68,22 +81,31 @@ let allowedDirectories = (await Promise.all( // Filter to only accessible directories, warn about inaccessible ones const accessibleDirectories: string[] = []; +const invalidDirectories: InvalidAllowedDirectory[] = []; for (const dir of allowedDirectories) { try { const stats = await fs.stat(dir); if (stats.isDirectory()) { accessibleDirectories.push(dir); } else { - console.error(`Warning: ${dir} is not a directory, skipping`); + const reason = "not a directory"; + invalidDirectories.push({ directory: dir, reason }); + console.error(`Warning: Skipping invalid allowed directory "${dir}": ${reason}`); } } catch (error) { - console.error(`Warning: Cannot access directory ${dir}, skipping`); + const reason = `cannot access: ${formatStartupValidationError(error)}`; + invalidDirectories.push({ directory: dir, reason }); + console.error(`Warning: Skipping invalid allowed directory "${dir}": ${reason}`); } } // Exit only if ALL paths are inaccessible (and some were specified) if (accessibleDirectories.length === 0 && allowedDirectories.length > 0) { console.error("Error: None of the specified directories are accessible"); + console.error("Invalid allowed directories:"); + for (const { directory, reason } of invalidDirectories) { + console.error(` - ${directory}: ${reason}`); + } process.exit(1); }