How do you sandbox the Filesystem MCP server?
Give it one project folder and nothing more. Pass that folder as the only allowed directory, or run the Docker image with the folder bind-mounted under /projects, read-only where reads are enough, and with networking switched off. Keep secrets out of that folder, and confirm what the server can see before you let an assistant write.
Cite
CodeLifter Forum, "How do you sandbox the Filesystem MCP server?", https://forum.codelifter.com/posts/how-do-you-sandbox-the-filesystem-mcp-server/, accessed 2026-10-16.- CodeLifter editorsStaffStaff, CodeLifter ·
What the server can reach by default
The reference Filesystem server restricts every operation to its allowed directories. Its README says "All filesystem operations are restricted to allowed directories" and that the server "requires at least ONE allowed directory to operate." Inside those directories it can read any file, write new files, overwrite existing ones with
write_file, edit withedit_file, and move or rename withmove_file, which the README's annotation table marks as destructive ("Deletes source file"). The README documents no undo or trash.There are two ways the allowed list gets set, and the difference matters for sandboxing:
- Command-line arguments. The paths after the package name in your config.
- MCP Roots. If your client supports Roots, the README says roots sent by the client "completely replace any server-side Allowed directories". The README recommends this method because the list can change at runtime without a restart.
So if your client sends roots, the folders you typed in the config are not the ones in force. Check which applies before you rely on either.
Step 1: narrow the allowed directories
Point the server at the project you are working on, not your home folder or Desktop. With npx, the config in
claude_desktop_config.json(or your client's equivalent) looks like this:{ "mcpServers": { "filesystem": { "command": "npx", "args": ["-y", "@modelcontextprotocol/server-filesystem", "/Users/you/code/my-app"] } } }In VS Code, the README's example uses
${workspaceFolder}as the path, which limits the server to the open workspace. On Windows the README says to launch npx throughcmd /c, so the command becomescmdand the arguments start with"/c", "npx".Step 2: run it in a container with read-only mounts
The npx route runs the server as you, with your user's file permissions. A container adds a second boundary: the server can only see what you mount. The README's Docker example mounts host folders under
/projectsand notes that "Adding theroflag will make the directory readonly by the server." Docker's own bind mount documentation says bind mounts "have write access to files on the host by default" and that you can use thereadonlyorrooption to prevent writes.{ "mcpServers": { "filesystem": { "command": "docker", "args": [ "run", "-i", "--rm", "--network", "none", "--mount", "type=bind,src=/Users/you/code/my-app,dst=/projects/my-app", "--mount", "type=bind,src=/Users/you/code/shared-docs,dst=/projects/docs,ro", "mcp/filesystem", "/projects" ] } } }The
--network noneflag is our addition, not part of the README's example. Docker's none network driver page says it will "completely isolate the networking stack of a container" so that "only the loopback device is created." The README states that every tool setsopenWorldHint: falseand that the server "only accesses the local filesystem," and stdio needs no network, so the flag should not change how it works. Test it with your client before you depend on it.Step 3: keep secrets out of the allowed folders
The server's
read_text_filetool "Always treats the file as UTF-8 text regardless of extension", so an.envfile, an SSH key or a cloud credentials file inside an allowed folder can be read like any other file. Before you start:- Move secrets out of the project folder, or mount only the subfolders the assistant needs (for example
src/anddocs/, not the repository root). - Do not allow your home directory. It usually contains
~/.ssh, shell history and tool configs. - If a token has to sit in the project, assume the assistant can read it, and scope that token tightly. The thread on GitHub MCP token scopes covers that for GitHub.
Step 4: keep a human on the write tools
Sandboxing limits where damage can happen. It does not stop damage inside the folder. Turn on your client's per-call approval for
write_file,edit_fileandmove_file. The README advises usingedit_filewithdryRunfirst, which returns a diff without applying it. The MCP tools specification also says clients "MUST consider tool annotations to be untrusted unless they come from trusted servers", so treat a read-only hint as a label, not a lock. A read-only mount is the lock. Commit your work to git before a session so a bad overwrite can be reverted.Which control limits what
Control Limits Does not limit One allowed directory (args) Paths the server will touch Anything inside that folder; replaced if the client sends Roots Roots from the client Paths, and they can change at runtime Same as above; you rely on the client's choice of roots Docker bind mounts What the process can see at all Writes to mounts without roroon a mountWrites to that folder Reads, including secrets in it --network noneNetwork access from the container File access inside the mounts Client approval prompts Which calls run Calls you approve without reading Check the sandbox before you work
- Ask the assistant to call
list_allowed_directoriesand read the result yourself. With Docker it should show only paths under/projects. - Ask it to read a file outside those paths. The call should fail.
- Ask it to create a file in a folder you mounted with
ro. The call should fail. - Repeat after any client update, because Roots behaviour depends on the client.
The CodeLifter page on the Filesystem MCP server lists every tool and its annotation. If you are choosing between local and hosted servers more generally, see remote or local GitHub MCP server, which walks through the same trade-off for GitHub.
Write something first.
Give people something to work with: at least 30 words on what happened and what you tried.
That is too long. Keep it under 6,000 characters.
Write the question as the title, 15 to 140 characters, no links.
Pick a category.
Add a name (2 to 40 characters, no links).
That email address does not look right.
That was quick. Read the thread, then try again.
The form expired. Reload the page and post again.
Something went wrong with the form. Reload and try again.
Please complete the check and post again.
Limit reached for now. Try again later.
This thread is closed to new replies.
This thread no longer accepts replies.
Something went wrong with the form. Reload and try again.
Post a reply or question first (name and email), then this browser can vote, edit and accept answers.
You cannot vote on your own post.
Only the author (within 30 days) or the forum team can do that.
That email belongs to a forum team account. Use your sign-in link instead.
New accounts are paused for the moment. Try again later.
That was already posted.