modelcontextprotocol / modelcontextprotocol/servers

Filesystem MCP: Server should wait inital roots to be loaded before handling tool calls

Open
#3,204 3 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

enhancement
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

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

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.