
Services
The file system MCP server is @modelcontextprotocol/server-filesystem 1.0.0. Pass one directory. It can read and write inside that directory, and it denies paths outside it.

A file system MCP server lets an agent read and write files on the machine where the process runs. The official one is @modelcontextprotocol/server-filesystem version 1.0.0. It is not read-only. It will write any file inside the directories you pass on the command line, and it will refuse a path outside them.
By Tayyab Javed, AI agent developer
Pass one absolute directory. I installed 1.0.0 and launched dist/index.js with a temp folder. A read inside it returned the file. A read outside, a .. path, and a symlink pointing outside were all denied. write_file created a file inside the folder and created nothing outside it.
It is a local stdio process. The host starts it and talks JSON-RPC on stdin. The published tools include read_text_file, list_directory, search_files, and also write_file, edit_file, and move_file. There is no flag on the binary I ran that turns the writes off. The other MCP pieces are indexed on the MCP servers hub.
The directories are command-line arguments. Give a project folder, not your home directory and not /. This is the host config. I did not shell out through npx. I ran the same package's dist/index.js under Node with one directory argument, which is what that config starts.
{
"mcpServers": {
"filesystem": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem@1.0.0", "/absolute/path/to/one/folder"]
}
}
}
With the client I used, stderr said the client does not support MCP Roots, so the server kept the directory from the arguments. list_allowed_directories printed that folder and nothing else. read_text_file on a file inside it returned the file text. The same tool on /tmp/mcp-secret-outside.txt returned is_error true: Access denied - path outside allowed directories. A path that climbed out with .. was resolved and denied the same way. A symlink inside the folder pointing at that outside file was denied with Access denied - symlink target outside allowed directories.
write_file inside the folder returned Successfully wrote to that path, and the bytes were on disk. The same call with a path outside the folder returned the access-denied error, and the target file did not exist afterward. If you start the binary with no directory, and the client does not offer roots, it exits. The stderr I got said: No allowed directories available.
No. Allowed means allowed to read and to write. The README documents a Docker bind mount with an ro flag when you want the mount itself to be read-only. I did not run that container. If you stay on npx, the scope is the directory list, and writes inside it succeed. Roots are a second way in. A client that supports roots replaces the command-line directories with its own list. I did not test that replacement. Treat a roots-capable host as able to widen the directory unless you have checked what it sends.
Do not put a credential file, an SSH directory, or a production checkout in the argument list. Auth for a server other people can call is a different problem, covered in MCP server authentication. This binary is a local process. Putting a process on a public URL is how to deploy an MCP server.
I call list_allowed_directories before any read or write. The answer has to be the one folder I passed, and no parent of it. Then I try a path outside that folder, a path that climbs with .., and a symlink whose target sits outside. All three should be denied, and a write outside should create nothing. The mistake is passing a home directory, an SSH folder, or a production checkout. This binary has no switch that turns writes off. My default is one absolute directory made for the agent, with no credential file in it, and the package pinned. If the host supports roots, I read the list it sends, because that list can replace the arguments.
Add the npm package at version 1.0.0 to the host config and pass one absolute directory as the last argument. Call list_allowed_directories before you call anything else. The answer should be that directory and no parent of it.
Not on 1.0.0. A symlink inside the allowed directory whose target sat outside it was rejected, with the target path named in the error. A .. path was rejected the same way.
Free 30-minute scoping call. We will name the one folder, and what is not allowed to sit inside it.
Book a Scoping Call