The Filesystem MCP Server is a Node.js server that provides secure filesystem operations through the Model Context Protocol (MCP) with dynamic access control.
File Operations:
Read: Text files (complete or specific lines), media files (base64 encoded with MIME types), or multiple files concurrently
Write & Edit: Create new files, overwrite existing ones, or perform selective line-based edits with diff previews
Move: Rename or move files and directories within allowed paths
Metadata: Retrieve detailed information including size, timestamps, type, and permissions
Directory Operations:
Create: New directories including nested paths
List: Directory contents with file/subdirectory distinction and sorting options
Search: Recursively find files and directories matching patterns with exclusion options
Tree View: Get recursive JSON structure of directory hierarchies
Access Control:
Static Control: Restrict operations to directories set via command-line
Dynamic Control: Update allowed directories using MCP Roots to override server-side configurations
Access Listing: View currently permitted directories
Filesystem MCP Server
Node.js server implementing Model Context Protocol (MCP) for filesystem operations.
Features
Read/write files
Create/list/delete directories
Move files/directories
Search files
Get file metadata
Dynamic directory access control via Roots
Related MCP server: Readonly Filesystem MCP Server
Directory Access Control
The server uses a flexible directory access control system. Directories can be specified via command-line arguments or dynamically via Roots.
Method 1: Command-line Arguments
Specify Allowed directories when starting the server:
Method 2: MCP Roots (Recommended)
MCP clients that support Roots can dynamically update the Allowed directories.
Roots notified by Client to Server, completely replace any server-side Allowed directories when provided.
Important: If server starts without command-line arguments AND client doesn't support roots protocol (or provides empty roots), the server will throw an error during initialization.
This is the recommended method, as this enables runtime directory updates via roots/list_changed notifications without server restart, providing a more flexible and modern integration experience.
How It Works
The server's directory access control follows this flow:
Server Startup
Server starts with directories from command-line arguments (if provided)
If no arguments provided, server starts with empty allowed directories
Client Connection & Initialization
Client connects and sends
initializerequest with capabilitiesServer checks if client supports roots protocol (
capabilities.roots)
Roots Protocol Handling (if client supports roots)
On initialization: Server requests roots from client via
roots/listClient responds with its configured roots
Server replaces ALL allowed directories with client's roots
On runtime updates: Client can send
notifications/roots/list_changedServer requests updated roots and replaces allowed directories again
Fallback Behavior (if client doesn't support roots)
Server continues using command-line directories only
No dynamic updates possible
Access Control
All filesystem operations are restricted to allowed directories
Use
list_allowed_directoriestool to see current directoriesServer requires at least ONE allowed directory to operate
Note: The server will only allow operations within directories specified either via args or via Roots.
API
Tools
read_text_file
Read complete contents of a file as text
Inputs:
path(string)head(number, optional): First N linestail(number, optional): Last N lines
Always treats the file as UTF-8 text regardless of extension
Cannot specify both
headandtailsimultaneously
read_media_file
Read an image or audio file
Inputs:
path(string)
Streams the file and returns base64 data with the corresponding MIME type
read_multiple_files
Read multiple files simultaneously
Input:
paths(string[])Failed reads won't stop the entire operation
write_file
Create new file or overwrite existing (exercise caution with this)
Inputs:
path(string): File locationcontent(string): File content
edit_file
Make selective edits using advanced pattern matching and formatting
Features:
Line-based and multi-line content matching
Whitespace normalization with indentation preservation
Multiple simultaneous edits with correct positioning
Indentation style detection and preservation
Git-style diff output with context
Preview changes with dry run mode
Inputs:
path(string): File to editedits(array): List of edit operationsoldText(string): Text to search for (can be substring)newText(string): Text to replace with
dryRun(boolean): Preview changes without applying (default: false)
Returns detailed diff and match information for dry runs, otherwise applies changes
Best Practice: Always use dryRun first to preview changes before applying them
create_directory
Create new directory or ensure it exists
Input:
path(string)Creates parent directories if needed
Succeeds silently if directory exists
list_directory
List directory contents with [FILE] or [DIR] prefixes
Input:
path(string)
list_directory_with_sizes
List directory contents with [FILE] or [DIR] prefixes, including file sizes
Inputs:
path(string): Directory path to listsortBy(string, optional): Sort entries by "name" or "size" (default: "name")
Returns detailed listing with file sizes and summary statistics
Shows total files, directories, and combined size
move_file
Move or rename files and directories
Inputs:
source(string)destination(string)
Fails if destination exists
search_files
Recursively search for files/directories that match or do not match patterns
Inputs:
path(string): Starting directorypattern(string): Search patternexcludePatterns(string[]): Exclude any patterns.
Glob-style pattern matching
Returns full paths to matches
directory_tree
Get recursive JSON tree structure of directory contents
Inputs:
path(string): Starting directoryexcludePatterns(string[]): Exclude any patterns. Glob formats are supported.
Returns:
JSON array where each entry contains:
name(string): File/directory nametype('file'|'directory'): Entry typechildren(array): Present only for directoriesEmpty array for empty directories
Omitted for files
Output is formatted with 2-space indentation for readability
get_file_info
Get detailed file/directory metadata
Input:
path(string)Returns:
Size
Creation time
Modified time
Access time
Type (file/directory)
Permissions
list_allowed_directories
List all directories the server is allowed to access
No input required
Returns:
Directories that this server can read/write from
Usage with Claude Desktop
Add this to your claude_desktop_config.json:
Note: you can provide sandboxed directories to the server by mounting them to /projects. Adding the ro flag will make the directory readonly by the server.
Docker
Note: all directories must be mounted to /projects by default.
NPX
Usage with VS Code
For quick installation, click the installation buttons below...
For manual installation, you can configure the MCP server using one of these methods:
Method 1: User Configuration (Recommended)
Add the configuration to your user-level MCP configuration file. Open the Command Palette (Ctrl + Shift + P) and run MCP: Open User Configuration. This will open your user mcp.json file where you can add the server configuration.
Method 2: Workspace Configuration
Alternatively, you can add the configuration to a file called .vscode/mcp.json in your workspace. This will allow you to share the configuration with others.
For more details about MCP configuration in VS Code, see the official VS Code MCP documentation.
You can provide sandboxed directories to the server by mounting them to /projects. Adding the ro flag will make the directory readonly by the server.
Docker
Note: all directories must be mounted to /projects by default.
NPX
Build
Docker build:
License
This MCP server is licensed under the MIT License. This means you are free to use, modify, and distribute the software, subject to the terms and conditions of the MIT License. For more details, please see the LICENSE file in the project repository.