-
Notifications
You must be signed in to change notification settings - Fork 9.3k
Open
Labels
enhancementNew feature or requestNew feature or request
Description
Is your feature request related to a problem? Please describe.
When intial roots are used in MCP client to connect to a file system server, tool calls can happen before initial roots are loaded. This causes the server to complain about:
Updated allowed directories from MCP roots: 1 valid directories
Access denied - path outside allowed directories: C:\temp not in
Steps to replicate:
(I also documented how I discovered this issue here: #3174 (comment))
Client code:
async function list() {
const transport = new StdioClientTransport({
command: "node",
args: ["../mcp-servers/src/filesystem/dist/index.js"],
});
if (!transport) {
throw new Error("Transport not available");
}
// Initialize the client
const client = new MCPClient(
{
name: "test-fs-client",
version: "1.0.0",
},
{
capabilities: {
roots: {
listChanged: true,
},
},
}
);
client.setRequestHandler(ListRootsRequestSchema, async (notification) => {
console.log("Received roots/list_roots notification:", notification);
return {
roots: [
{
uri: "file:///C:/temp",
name: "My Project",
},
],
};
});
await client.connect(transport, {});
const result = await client?.callTool({
name: "list_directory",
arguments: {
path: "C:/temp",
},
});
await client.close();
// @ts-expect-error ignore type
const stdout = result?.content[0]?.text;
// @ts-expect-error ignore type
const stderr = result?.content[1]?.text;
let output = `\
stdout:
\`\`\`
${stdout}
\`\`\`
`;
if (stderr) {
output += `\
stderr:
\`\`\`
${stderr}
\`\`\`
`;
}
return output;
}
const result = await list();
console.log("Command output:", result);Terminal output
Usage: mcp-server-filesystem [allowed-directory] [additional-directories...]
Note: Allowed directories can be provided via:
1. Command-line arguments (shown above)
2. MCP roots protocol (if client supports it)
At least one directory must be provided by EITHER method for the server to operate.
Secure MCP Filesystem Server running on stdio
Started without allowed directories - waiting for client to provide roots via MCP protocol
Received roots/list_roots notification: { method: 'roots/list' }
Updated allowed directories from MCP roots: 1 valid directories
Command output: stdout:
Access denied - path outside allowed directories: C:\temp not inDescribe the solution you'd like
- Option 1: The Roots Protocal should include a notification event after initial roots are loaded/updated, then the client can know when to handle subsequent operations.
servers/src/filesystem/index.ts
Lines 687 to 696 in 861c11b
async function updateAllowedDirectoriesFromRoots(requestedRoots: Root[]) { const validatedRootDirs = await getValidRootDirectories(requestedRoots); if (validatedRootDirs.length > 0) { allowedDirectories = [...validatedRootDirs]; setAllowedDirectories(allowedDirectories); // Update the global state in lib.ts console.error(`Updated allowed directories from MCP roots: ${validatedRootDirs.length} valid directories`); } else { console.error("No valid root directories provided by client"); } } - Option 2: The file server can queue up incoming requests until initial roots are loaded, so that client developers do need to handle this explicitly.
- Option 3: Or, it should mention in https://modelcontextprotocol.io/specification/2025-11-25/client/roots#implementation-guidelines that the client might need to wait a little for server to load initial roots.
Describe alternatives you've considered
This is a temporary workaround that I am not a fan of. But it works for now by waiting a little before client calls the server.
client.setRequestHandler(ListRootsRequestSchema, async (notification) => {
console.log("Received roots/list_roots notification:", notification);
return {
roots: [
{
uri: "file:///C:/temp",
name: "My Project",
},
],
};
});
await client.connect(transport, {});
// wait 1 second
await new Promise((resolve) => setTimeout(resolve, 1000));
const result = await client?.callTool({
name: "list_directory",
arguments: {
path: "C:/temp",
},
});Metadata
Metadata
Assignees
Labels
enhancementNew feature or requestNew feature or request