modelcontextprotocol / modelcontextprotocol/servers
Filesystem MCP: Server should wait inital roots to be loaded before handling tool calls
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 90.5k
- Forks
- 11.7k
- Avg merge
- 2d 2h
- Merged PRs (30d)
- 5
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: https://github.com/modelcontextprotocol/servers/issues/3174#issuecomment-3738231331)
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 in
Describe 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. https://github.com/modelcontextprotocol/servers/blob/861c11b786b3efbc87eb2e878a4039d33846a031/src/filesystem/index.ts#L687-L696
- 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",
},
});
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with src/filesystem/index.ts around the roots update logic referenced at lines 687-696, then reproduce the race using the TypeScript client example in the issue. Review the MCP roots implementation guidelines and determine which of the three proposed behaviors is appropriate; done means initial roots are reliably available before a filesystem tool call is handled.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- backend, backend-api-design
- Issue type
- Feature
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100