Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 14 additions & 2 deletions src/filesystem/__tests__/roots-utils.test.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,22 @@
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
import { getValidRootDirectories } from '../roots-utils.js';
import { formatEffectiveAllowedDirectories, getValidRootDirectories } from '../roots-utils.js';
import { mkdtempSync, rmSync, mkdirSync, writeFileSync, realpathSync } from 'fs';
import { tmpdir } from 'os';
import { join } from 'path';
import type { Root } from '@modelcontextprotocol/sdk/types.js';

describe('formatEffectiveAllowedDirectories', () => {
it('includes the source and effective directories', () => {
expect(formatEffectiveAllowedDirectories(['/workspace', '/data'], 'client-provided MCP Roots'))
.toBe('Effective allowed directories (source: client-provided MCP Roots):\n /workspace\n /data');
});

it('marks an empty effective directory set', () => {
expect(formatEffectiveAllowedDirectories([], 'none'))
.toBe('Effective allowed directories (source: none):\n (none)');
});
});

describe('getValidRootDirectories', () => {
let testDir1: string;
let testDir2: string;
Expand Down Expand Up @@ -81,4 +93,4 @@ describe('getValidRootDirectories', () => {
expect(result).toHaveLength(1);
});
});
});
});
19 changes: 16 additions & 3 deletions src/filesystem/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import { pathToFileURL } from "url";
import { z } from "zod";
import { minimatch } from "minimatch";
import { normalizePath, expandHome } from './path-utils.js';
import { getValidRootDirectories } from './roots-utils.js';
import { formatEffectiveAllowedDirectories, getValidRootDirectories } from './roots-utils.js';
import {
// Function imports
formatSize,
Expand Down Expand Up @@ -90,6 +90,12 @@ if (accessibleDirectories.length === 0 && allowedDirectories.length > 0) {

allowedDirectories = accessibleDirectories;

let allowedDirectoriesSource = allowedDirectories.length > 0 ? "server arguments" : "none";

function logEffectiveAllowedDirectories() {
console.error(formatEffectiveAllowedDirectories(allowedDirectories, allowedDirectoriesSource));
}

// Initialize the global allowedDirectories in lib.ts
setAllowedDirectories(allowedDirectories);

Expand Down Expand Up @@ -726,10 +732,13 @@ async function updateAllowedDirectoriesFromRoots(requestedRoots: Root[]) {
const validatedRootDirs = await getValidRootDirectories(requestedRoots);
if (validatedRootDirs.length > 0) {
allowedDirectories = [...validatedRootDirs];
allowedDirectoriesSource = "client-provided MCP Roots";
setAllowedDirectories(allowedDirectories); // Update the global state in lib.ts
console.error(`Updated allowed directories from MCP roots: ${validatedRootDirs.length} valid directories`);
logEffectiveAllowedDirectories();
} else {
console.error("No valid root directories provided by client");
console.error("No valid root directories provided by client; retaining current allowed directories");
logEffectiveAllowedDirectories();
}
}

Expand Down Expand Up @@ -757,14 +766,18 @@ server.server.oninitialized = async () => {
await updateAllowedDirectoriesFromRoots(response.roots);
} else {
console.error("Client returned no roots set, keeping current settings");
logEffectiveAllowedDirectories();
}
} catch (error) {
console.error("Failed to request initial roots from client:", error instanceof Error ? error.message : String(error));
logEffectiveAllowedDirectories();
}
} else {
if (allowedDirectories.length > 0) {
console.error("Client does not support MCP Roots, using allowed directories set from server args:", allowedDirectories);
console.error("Client does not support MCP Roots");
logEffectiveAllowedDirectories();
}else{
logEffectiveAllowedDirectories();
throw new Error(`Server cannot operate: No allowed directories available. Server was started without command-line directories and client either does not support MCP roots protocol or provided empty roots. Please either: 1) Start server with directory arguments, or 2) Use a client that supports MCP roots protocol and provides valid root directories.`);
}
}
Expand Down
10 changes: 9 additions & 1 deletion src/filesystem/roots-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,14 @@ import { normalizePath } from './path-utils.js';
import type { Root } from '@modelcontextprotocol/sdk/types.js';
import { fileURLToPath } from "url";

export function formatEffectiveAllowedDirectories(
directories: readonly string[],
source: string
): string {
const entries = directories.length > 0 ? directories.map(directory => ` ${directory}`) : [" (none)"];
return [`Effective allowed directories (source: ${source}):`, ...entries].join("\n");
}

/**
* Converts a root URI to a normalized directory path with basic security validation.
* @param rootUri - File URI (file://...) or plain directory path
Expand Down Expand Up @@ -74,4 +82,4 @@ export async function getValidRootDirectories(
}

return validatedDirectories;
}
}
Loading