bounded-filesystem-mcp
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@bounded-filesystem-mcp read the first 10,000 characters of error.log"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
bounded-filesystem-mcp
A fork of the Filesystem MCP server where every tool result has a size limit. Large files are read in windows instead of being returned in one piece.
Provenance
Vendored from modelcontextprotocol/servers, tag 2026.1.14 (commit 3e805376da81c063c2798410906b5fd134334a43), directory src/filesystem. This repository's history starts from that snapshot. Upstream is MIT licensed, copyright Anthropic, PBC; see LICENSE.
lib.ts, path-validation.ts, path-utils.ts, roots-utils.ts and their tests are unchanged from upstream (only __tests__/structured-content.test.ts is adapted, see below), so they can be synced by copying the files. The changes live in index.ts (tool registration) and the new bounded.ts.
Related MCP server: LocalFS MCP Server
Differences from upstream
Result cap. A text result longer than the cap (default 50,000 characters) keeps its first 50,000 characters, never splitting a surrogate pair. A notice is added on its own line:
[Result truncated: showing characters 1-50,000 of 1,234,567. Call again with offset=50000 to continue.]Tools that cannot page say how to narrow the request instead, for example:
[Result truncated: showing characters 1-50,000 of 812,345. To see the rest, narrow the request: pass a deeper path, or add excludePatterns.]Paged reads.
read_text_fileandread_filetakeoffsetandlimit, both counted in characters. Follow theoffsetin each notice to walk the whole file; the last window has no notice. The file is streamed and only the window is kept in memory.headandtailwork as before, but cannot be combined withoffsetorlimit.Capped listings.
read_multiple_files,directory_tree,search_files,list_directory,list_directory_with_sizesandedit_file's diff all use the cap.read_multiple_filescaps the combined text, and its notice says how many of the requested files were included in full. It reads the files one after another rather than in parallel.Media size limit.
read_media_filerefuses files over 5 MB (5,242,880 bytes) with an error naming the file size and the limit. It checks the size before reading any bytes.Plain text results. Tools have no
outputSchemaand return nostructuredContent, only content blocks. Hosts that preferstructuredContentwould otherwise see the text JSON-escaped and the payload doubled, so a capped result would not be the size the cap promises.The server reports itself as
bounded-filesystemininitialize. Tool names and existing parameters are unchanged.
"Characters" here means UTF-16 code units, the same as a JavaScript string's length.
Options
Flag | Environment variable | Default | Meaning |
|
|
| Largest text result, in characters, before the truncation notice |
|
|
| Largest file |
A flag wins over its environment variable. Both flags also accept the --flag=<n> form. Everything else on the command line is an allowed directory:
bunx bounded-filesystem-mcp@0.1.0 --max-result-chars 40000 /path/to/dir1 /path/to/dir2Features
Read/write files
Create/list/delete directories
Move files/directories
Search files
Get file metadata
Dynamic directory access control via Roots
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:
bounded-filesystem-mcp /path/to/dir1 /path/to/dir2Method 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, or a window of it
Inputs:
path(string)head(number, optional): First N linestail(number, optional): Last N linesoffset(integer, optional): Character position to start from (default 0)limit(integer, optional): Number of characters to return, clamped to the result cap
Always treats the file as UTF-8 text regardless of extension
Cannot specify both
headandtailsimultaneously, or combine either withoffset/limitResults over the cap end with a notice giving the
offsetto continue fromread_fileis the deprecated alias and behaves the same
read_media_file
Read an image or audio file
Inputs:
path(string)
Streams the file and returns base64 data with the corresponding MIME type
Files over
--max-media-bytes(default 5 MB) return an error without being read
read_multiple_files
Read multiple files simultaneously
Input:
paths(string[])Failed reads won't stop the entire operation
The combined text is capped; the notice says how many files were included in full
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
Tool annotations (MCP hints)
This server sets MCP ToolAnnotations on each tool so clients can:
Distinguish read‑only tools from write‑capable tools.
Understand which write operations are idempotent (safe to retry with the same arguments).
Highlight operations that may be destructive (overwriting or heavily mutating data).
The mapping for filesystem tools is:
Tool | readOnlyHint | idempotentHint | destructiveHint | Notes |
|
| – | – | Pure read |
|
| – | – | Pure read |
|
| – | – | Pure read |
|
| – | – | Pure read |
|
| – | – | Pure read |
|
| – | – | Pure read |
|
| – | – | Pure read |
|
| – | – | Pure read |
|
| – | – | Pure read |
|
|
|
| Re‑creating the same dir is a no‑op |
|
|
|
| Overwrites existing files |
|
|
|
| Re‑applying edits can fail or double‑apply |
|
|
|
| Move/rename only; repeat usually errors |
Note:
idempotentHintanddestructiveHintare meaningful only whenreadOnlyHintisfalse, as defined by the MCP spec.
Usage
MCP clients start the server over stdio:
{
"mcpServers": {
"filesystem": {
"command": "bunx",
"args": [
"bounded-filesystem-mcp@0.1.0",
"/Users/username/Desktop",
"/path/to/other/allowed/dir"
]
}
}
}npx -y bounded-filesystem-mcp@0.1.0 <dirs...> works the same way.
Build
npm install
npm run build
npm testLicense
MIT. The upstream code is copyright Anthropic, PBC; the changes in this fork are copyright Shivam Singh. See LICENSE.
Available Tools
14 toolscreate_directoryCreate DirectoryAIdempotent
Create a new directory or ensure a directory exists. Can create multiple nested directories in one operation. If the directory already exists, this operation will succeed silently. Perfect for setting up directory structures for projects or ensuring required paths exist. Only works within allowed directories.
Inputs: path (required).
directory_treeDirectory TreeARead-only
Get a recursive tree view of files and directories as a JSON structure. Each entry includes 'name', 'type' (file/directory), and 'children' for directories. Files have no children array, while directories always have a children array (which may be empty). The output is formatted with 2-space indentation for readability. Only works within allowed directories.
Inputs: path (required), excludePatterns.
edit_fileEdit FileADestructive
Make line-based edits to a text file. Each edit replaces exact line sequences with new content. Returns a git-style diff showing the changes made. Only works within allowed directories.
Inputs: path (required), edits (required), dryRun.
get_file_infoGet File InfoARead-only
Retrieve detailed metadata about a file or directory. Returns comprehensive information including size, creation time, last modified time, permissions, and type. This tool is perfect for understanding file characteristics without reading the actual content. Only works within allowed directories.
Inputs: path (required).
list_allowed_directoriesList Allowed DirectoriesARead-only
Returns the list of directories that this server is allowed to access. Subdirectories within these allowed directories are also accessible. Use this to understand which directories and their nested paths are available before trying to access files.
Inputs: no named parameters.
list_directoryList DirectoryARead-only
Get a detailed listing of all files and directories in a specified path. Results clearly distinguish between files and directories with [FILE] and [DIR] prefixes. This tool is essential for understanding directory structure and finding specific files within a directory. Only works within allowed directories.
Inputs: path (required).
list_directory_with_sizesList Directory with SizesARead-only
Get a detailed listing of all files and directories in a specified path, including sizes. Results clearly distinguish between files and directories with [FILE] and [DIR] prefixes. This tool is useful for understanding directory structure and finding specific files within a directory. Only works within allowed directories.
Inputs: path (required), sortBy.
move_fileMove FileA
Move or rename files and directories. Can move files between directories and rename them in a single operation. If the destination exists, the operation will fail. Works across different directories and can be used for simple renaming within the same directory. Both source and destination must be within allowed directories.
Inputs: source (required), destination (required).
read_fileRead File (Deprecated)ARead-only
Read the complete contents of a file as text. DEPRECATED: Use read_text_file instead. Use the 'offset' and 'limit' parameters to read a window of characters. Results longer than 50,000 characters are cut short, ending with a notice that says how to get the rest.
Inputs: path (required), head, tail, limit, +1 more.
read_media_fileRead Media FileARead-only
Read an image or audio file. Returns the base64 encoded data and MIME type. Files larger than 5,242,880 bytes are refused with an error. Only works within allowed directories.
Inputs: path (required).
read_multiple_filesRead Multiple FilesARead-only
Read the contents of multiple files simultaneously. This is more efficient than reading files one by one when you need to analyze or compare multiple files. Each file's content is returned with its path as a reference. Failed reads for individual files won't stop the entire operation. Results longer than 50,000 characters are cut short, ending with a notice that says how to get the rest. Only works within allowed directories.
Inputs: paths (required).
read_text_fileRead Text FileARead-only
Read the complete contents of a file from the file system as text. Handles various text encodings and provides detailed error messages if the file cannot be read. Use this tool when you need to examine the contents of a single file. Use the 'head' parameter to read only the first N lines of a file, or the 'tail' parameter to read only the last N lines of a file. Use the 'offset' and 'limit' parameters to read a window of characters, for example to continue after a truncated result; they cannot be combined with 'head' or 'tail'. Results longer than 50,000 characters are cut short, ending with a notice that says how to get the rest. Operates on the file as text regardless of extension. Only works within allowed directories.
Inputs: path (required), head, tail, limit, +1 more.
search_filesSearch FilesARead-only
Recursively search for files and directories matching a pattern. The patterns should be glob-style patterns that match paths relative to the working directory. Use pattern like '.ext' to match files in current directory, and '**/.ext' to match files in all subdirectories. Returns full paths to all matching items. Great for finding files when you don't know their exact location. Only searches within allowed directories.
Inputs: path (required), pattern (required), excludePatterns.
write_fileWrite FileADestructiveIdempotent
Create a new file or completely overwrite an existing file with new content. Use with caution as it will overwrite existing files without warning. Handles text content with proper encoding. Only works within allowed directories.
Inputs: path (required), content (required).
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 14 tools
Most tools target clearly distinct operations, but read_file is an explicitly deprecated near-duplicate of read_text_file, and list_directory vs list_directory_with_sizes differ only by an extra field, which invites misselection. The descriptions do help (flagging deprecation and size detail), keeping it from being worse than middling.
Strong snake_case verb_noun pattern throughout (read_file, write_file, create_directory, search_files, move_file). The only deviations are directory_tree, which is a bare noun with no verb, and the modifier suffixes on the read_*/list_* variants, which are still readable and predictable.
14 tools is a reasonable, well-scoped surface for a bounded filesystem server and nearly every tool earns its place. Minor bloat comes from a deprecated read_file alias and a listing variant that could be a parameter rather than its own tool.
The surface covers read, write, edit, move, search, and inspection well, but there is no delete/remove operation at all, and no copy tool. Agents attempting cleanup or duplication workflows will hit dead ends and have to fall back to overwriting or external means.
Related MCP Connectors
Safe folder access for ChatGPT and Claude: read, write and search files, risky tools opt-in.
Manage files and folders directly from your workspace. Read and write files, list directories, cre…
A real-time, multiplayer filesystem for agents and humans: shared files, live edits, history.
User-owned files and explicit AI Memories for authorized assistants with scoped access.
Related MCP Servers
- FlicenseAqualityDmaintenanceEnables secure filesystem operations with directory sandboxing and optional read-only mode. Supports file reading/writing, directory management, file searching, and text operations while restricting access to specified directories.12-
- FlicenseNot gradedqualityDmaintenanceProvides sandboxed access to local filesystem operations including directory and file management, content search with glob and regex patterns, and binary file support with configurable safety limits.-
- AlicenseNot gradedqualityDmaintenanceProvides secure filesystem access for AI assistants with optimizations like file reading limits and depth-limited traversal to improve token efficiency. It enables AI models to read, write, and search files within explicitly allowed directories while automatically skipping large system folders.4MIT
- AlicenseBqualityCmaintenanceEnables AI assistants to list directories, read, write, and search files within a locked root directory, using resolve-then-validate path checks, size caps, and binary detection to prevent sandbox escapes.4MIT