Skip to content

j0hanz/filesystem-mcp

Repository files navigation

Filesystem MCP Server

npm version License: MIT

Install in VS Code Install in VS Code Insiders Install in Visual Studio

Add to LM Studio Install in Cursor Install in Goose

A local filesystem MCP server that lets LLMs and AI agents read, write, search, diff, patch, and manage files safely and efficiently. Built for reliable, structured, and controlled filesystem interaction.

Overview

A secure, production-ready Model Context Protocol server that gives AI assistants controlled access to the local filesystem. All operations are sandboxed to explicitly allowed directories with path traversal prevention, sensitive file blocking, and optional Bearer token authentication.

Supports stdio (default) and Streamable HTTP transport with SSE support. HTTP sessions are implemented with isolated per-session server state.

Key Features

  • 18 filesystem tools — read, write, search, diff, patch, hash, and bulk operations with structured output schemas
  • Security-first — path validation, symlink escape prevention, sensitive file denylist, localhost-only CORS, optional API key auth
  • Dual transport — stdio for local use, Streamable HTTP with SSE for networked/multi-session deployments
  • Structured output — all tools return typed outputSchema / structuredContent for reliable LLM parsing
  • Self-documenting — 6 built-in resources (internal://instructions, internal://tool-catalog, etc.) and 4 built-in prompts (get-help, compare-files, analyze-path, get-tool-help)

Requirements

  • Node.js >= 24

Quick Start

{
  "mcpServers": {
    "filesystem": {
      "command": "npx",
      "args": ["-y", "@j0hanz/filesystem-mcp@latest"]
    }
  }
}

Docker

docker run -i --rm -v /path/to/project:/workspace:ro ghcr.io/j0hanz/filesystem-mcp /workspace

Or using Docker Compose:

services:
  filesystem-mcp:
    build: .
    stdin_open: true
    volumes:
      - ./:/projects/workspace:ro
    command: ['/projects/workspace']

CLI Usage

filesystem-mcp [options] [allowedDirs...]

Arguments:
  allowedDirs              Directories the server can access

Options:
  --allow-cwd              Allow the current working directory as an additional root
  --port <number>          Enable HTTP transport on the given port
  -v, --version            Display server version
  -h, --help               Display help

Examples:
  $ npx @j0hanz/filesystem-mcp@latest /path/to/project
  $ npx @j0hanz/filesystem-mcp@latest --allow-cwd
  $ npx @j0hanz/filesystem-mcp@latest --port 3000 /path/to/project

Client Configuration

Install in VS Code

Install in VS Code

Add to .vscode/mcp.json:

{
  "servers": {
    "filesystem": {
      "command": "npx",
      "args": ["-y", "@j0hanz/filesystem-mcp@latest"]
    }
  }
}

Or install via CLI:

code --add-mcp '{"name":"filesystem","command":"npx","args":["-y","@j0hanz/filesystem-mcp@latest"]}'
Install in VS Code Insiders

Install in VS Code Insiders

Add to .vscode/mcp.json:

{
  "servers": {
    "filesystem": {
      "command": "npx",
      "args": ["-y", "@j0hanz/filesystem-mcp@latest"]
    }
  }
}

Or install via CLI:

code-insiders --add-mcp '{"name":"filesystem","command":"npx","args":["-y","@j0hanz/filesystem-mcp@latest"]}'
Install in Cursor

Install in Cursor

Add to ~/.cursor/mcp.json:

{
  "mcpServers": {
    "filesystem": {
      "command": "npx",
      "args": ["-y", "@j0hanz/filesystem-mcp@latest"]
    }
  }
}
Install in Visual Studio

Install in Visual Studio

Add to <SOLUTIONDIR>.mcp.json or %USERPROFILE%\.mcp.json:

{
  "servers": {
    "filesystem": {
      "command": "npx",
      "args": ["-y", "@j0hanz/filesystem-mcp@latest"]
    }
  }
}
Install in Goose

Install in Goose

Add to ~/.config/goose/config.yaml:

extensions:
  filesystem:
    name: Filesystem MCP
    cmd: npx
    args:
      - -y
      - '@j0hanz/filesystem-mcp@latest'
    enabled: true
    type: stdio
Add to LM Studio

Add to LM Studio

{
  "mcpServers": {
    "filesystem": {
      "command": "npx",
      "args": ["-y", "@j0hanz/filesystem-mcp@latest"]
    }
  }
}
Install in Claude Desktop

Add to claude_desktop_config.json:

{
  "mcpServers": {
    "filesystem": {
      "command": "npx",
      "args": ["-y", "@j0hanz/filesystem-mcp@latest"]
    }
  }
}
Install in Claude Code
claude mcp add filesystem-mcp -- npx -y @j0hanz/filesystem-mcp@latest

Or add a project-scoped .mcp.json:

{
  "mcpServers": {
    "filesystem": {
      "command": "npx",
      "args": ["-y", "@j0hanz/filesystem-mcp@latest"]
    }
  }
}
Install in Windsurf

Add to ~/.codeium/windsurf/mcp_config.json:

{
  "mcpServers": {
    "filesystem": {
      "command": "npx",
      "args": ["-y", "@j0hanz/filesystem-mcp@latest"]
    }
  }
}
Install in Amp
amp mcp add filesystem-mcp -- npx -y @j0hanz/filesystem-mcp@latest

Or add to settings.json:

{
  "amp.mcpServers": {
    "filesystem": {
      "command": "npx",
      "args": ["-y", "@j0hanz/filesystem-mcp@latest"]
    }
  }
}
Install in Cline

Add to cline_mcp_settings.json:

{
  "mcpServers": {
    "filesystem": {
      "command": "npx",
      "args": ["-y", "@j0hanz/filesystem-mcp@latest"]
    }
  }
}
Install in Codex
codex mcp add filesystem -- npx -y @j0hanz/filesystem-mcp@latest

Or add to ~/.codex/config.toml (or .codex/config.toml in a trusted project):

[mcp_servers.filesystem]
command = "npx"
args = ["-y", "@j0hanz/filesystem-mcp@latest"]
Install in GitHub Copilot Coding Agent

Add this JSON in your repository's GitHub Copilot coding agent MCP configuration:

{
  "mcpServers": {
    "filesystem": {
      "type": "local",
      "command": "npx",
      "args": ["-y", "@j0hanz/filesystem-mcp@latest"],
      "tools": ["*"]
    }
  }
}
Install in Warp
{
  "mcpServers": {
    "filesystem": {
      "command": "npx",
      "args": ["-y", "@j0hanz/filesystem-mcp@latest"]
    }
  }
}
Install in Kiro

Add to .kiro/settings/mcp.json:

{
  "mcpServers": {
    "filesystem": {
      "command": "npx",
      "args": ["-y", "@j0hanz/filesystem-mcp@latest"]
    }
  }
}
Install in Gemini CLI

Add to ~/.gemini/settings.json:

{
  "mcpServers": {
    "filesystem": {
      "command": "npx",
      "args": ["-y", "@j0hanz/filesystem-mcp@latest"]
    }
  }
}
Install in Zed

Add to ~/.config/zed/settings.json:

{
  "context_servers": {
    "filesystem": {
      "command": "npx",
      "args": ["-y", "@j0hanz/filesystem-mcp@latest"],
      "env": {}
    }
  }
}
Install in Augment

Add to VS Code settings.json under augment.advanced:

{
  "augment.advanced": {
    "mcpServers": [
      {
        "id": "filesystem",
        "command": "npx",
        "args": ["-y", "@j0hanz/filesystem-mcp@latest"]
      }
    ]
  }
}
Install in Roo Code
{
  "mcpServers": {
    "filesystem": {
      "command": "npx",
      "args": ["-y", "@j0hanz/filesystem-mcp@latest"]
    }
  }
}
Install in Kilo Code
{
  "mcpServers": {
    "filesystem": {
      "command": "npx",
      "args": ["-y", "@j0hanz/filesystem-mcp@latest"]
    }
  }
}

Use Cases

Explore and Understand a Codebase

Discover project structure and navigate unfamiliar repositories. Start with roots to see allowed directories, use tree for an overview, find to locate files by pattern, and read or read_many to inspect contents.

Relevant tools: roots, ls, find, tree, read, read_many, stat

Search Across Files

Locate specific code patterns, function definitions, or configuration values across a project. Use grep for content search with regex support and find for file name matching.

Relevant tools: grep, find

Edit and Refactor Code

Make precise, targeted edits to source files. Use edit for surgical replacements with dry-run preview, or search_and_replace for bulk changes across multiple files matching a glob pattern.

Relevant tools: edit, search_and_replace, write

Diff and Patch Workflow

Compare file versions and apply patches. Generate a unified diff with diff_files, preview with apply_patch(dryRun: true), then apply. Supports both single-file and multi-file patches (best-effort per file with per-file results[]).

Relevant tools: diff_files, apply_patch

File Management

Create directories, move/rename files, delete files, and verify file integrity via SHA-256 hashing.

Relevant tools: mkdir, mv, rm, calculate_hash, write

Architecture

[MCP Client]
    |
    | Transport: stdio (default) or Streamable HTTP + SSE (--port)
    v
[MCP Server: filesystem-mcp]
    | Entry: src/index.ts -> src/server/bootstrap.ts
    |
    +-- initialize / initialized
    |
    +-- tools/call ──────────────────────────────────────────
    |   +-- [roots]             — List allowed workspace roots
    |   +-- [ls]                — List directory contents
    |   +-- [find]              — Find files by glob
    |   +-- [tree]              — Render directory tree
    |   +-- [read]              — Read file contents
    |   +-- [read_many]         — Read multiple files
    |   +-- [stat]              — Get file metadata
    |   +-- [stat_many]         — Get multiple file metadata
    |   +-- [grep]              — Search file contents
    |   +-- [mkdir]             — Create directory
    |   +-- [write]             — Write file
    |   +-- [edit]              — Edit file (string replacements)
    |   +-- [mv]                — Move/rename file
    |   +-- [rm]                — Delete file
    |   +-- [calculate_hash]    — SHA-256 hash
    |   +-- [diff_files]        — Unified diff
    |   +-- [apply_patch]       — Apply unified patch
    |   +-- [search_and_replace]— Bulk search & replace
    |
    +-- resources/read ──────────────────────────────────────
    |   +-- internal://instructions
    |   +-- internal://tool-catalog
    |   +-- internal://workflows
    |   +-- internal://tool-info/{name}
    |   +-- filesystem-mcp://result/{id}
    |   +-- filesystem-mcp://metrics
    |
    +-- prompts/get ─────────────────────────────────────────
    |   +-- get-help (optional topic argument)
    |   +-- compare-files (original, modified)
    |   +-- analyze-path (path)
    |   +-- get-tool-help (name)
    |
    +-- Capabilities: logging, resources, tools, prompts, completions, tasks

Request Lifecycle

[Client] -- initialize {protocolVersion, capabilities} --> [Server]
[Server] -- {protocolVersion, capabilities, serverInfo} --> [Client]
[Client] -- notifications/initialized --> [Server]
[Client] -- tools/call {name, arguments} --> [Server]
[Server] -- validate(inputSchema) --> [Handler]
[Handler] -- {content: [{type, text}], structuredContent?, isError?} --> [Client]

MCP Surface

Tools

roots

List allowed workspace roots. Call first — all other tools are scoped to these directories.

No parameters.


ls

List immediate directory contents: name, path, type, size, modified date.

Parameter Type Required Description
path string no Base directory (default: root)
includeHidden boolean no Include dotfiles. Default: false
includeIgnored boolean no Include ignored items (node_modules, .git). Default: false
maxDepth integer no Max recursion depth (1-100) when pattern is provided
maxEntries integer no Max entries before truncation. Default: 1000, Max: 10000
sortBy enum no name | size | modified | type. Default: name
pattern string no Glob filter (e.g. **/*.ts)
includeSymlinkTargets boolean no Resolve symlink targets. Default: false
cursor string no Pagination cursor from a previous response

find

Find files by glob pattern. Returns matching files with metadata.

Parameter Type Required Description
path string no Base directory (default: root)
pattern string yes Glob pattern (e.g. **/*.ts)
maxResults integer no Max results (1-100000). Default: 1000
includeIgnored boolean no Include ignored items. Default: false
includeHidden boolean no Include dotfiles. Default: false
sortBy enum no path | name | size | modified. Default: path
maxDepth integer no Max directory depth (0-1000)
cursor string no Pagination cursor

tree

Render a directory tree with bounded recursion. Returns ASCII tree + structured JSON.

Parameter Type Required Description
path string no Base directory (default: root)
maxDepth integer no Depth (0 = root node only). Default: 10, Max: 100
maxEntries integer no Max entries. Default: 5000, Max: 100000
includeHidden boolean no Include dotfiles. Default: false
includeIgnored boolean no Include ignored items. Default: false
includeSizes boolean no Include file sizes in tree entries. Default: false

read

Read text file contents. Use head/tail to preview first/last N lines of large files.

Parameter Type Required Description
path string yes Absolute path to file
head integer no Read first N lines (1-100000)
tail integer no Read last N lines (1-100000)
startLine integer no Start line (1-based, inclusive)
endLine integer no End line (1-based, inclusive). Requires startLine
includeHash boolean no Include SHA-256 hash of full file content. Default: false

read_many

Read multiple text files in one request.

Parameter Type Required Description
paths string[] yes Files to read (1-100 paths)
head integer no Read first N lines of each file
tail integer no Read last N lines of each file
startLine integer no Start line (1-based) per file
endLine integer no End line (1-based) per file

stat

Get file/directory metadata: size, modified, permissions, mime, tokenEstimate.

Parameter Type Required Description
path string yes Absolute path to file or directory

stat_many

Get metadata for multiple files/directories in one request.

Parameter Type Required Description
paths string[] yes File/directory paths (1-100)

grep

Search file contents (grep-like). Returns matching lines with optional context.

Parameter Type Required Description
path string no Base directory (default: root)
pattern string yes Search text or RE2 regex when isRegex=true
isRegex boolean no Treat pattern as RE2 regex. Default: false
caseSensitive boolean no Case-sensitive matching. Default: false
wholeWord boolean no Match whole words only. Default: false
contextLines integer no Lines of context before/after (0-50). Default: 0
maxResults integer no Max match rows (1-100000). Default: 100
filePattern string no Glob for candidate files (e.g. **/*.ts)
includeHidden boolean no Include dotfiles. Default: false
includeIgnored boolean no Include ignored items. Default: false

mkdir

Create a new directory (recursive). Idempotent.

Parameter Type Required Description
path string no Absolute path to directory to create
paths string[] no Multiple directories to create. Either path or paths required

write

Write content to a file, overwriting all existing content. Creates parent directories if needed.

Parameter Type Required Description
path string yes Absolute path to file
content string yes Content to write

edit

Apply sequential literal string replacements (first occurrence per edit). Use dryRun to preview.

Parameter Type Required Description
path string yes Absolute path to file
edits array yes List of {oldText, newText} replacements
dryRun boolean no Preview edits without writing. Default: false
ignoreWhitespace boolean no Treat whitespace sequences as equivalent. Default: false

mv

Move or rename a file or directory.

Parameter Type Required Description
source string no Single path to move (deprecated: use sources)
sources string[] no Paths to move. Either source or sources required
destination string yes Destination path

rm

Permanently delete a file or directory. Irreversible.

Parameter Type Required Description
path string yes Absolute path to file or directory
recursive boolean no Delete non-empty directories. Default: false
ignoreIfNotExists boolean no No error if missing. Default: false

calculate_hash

Calculate SHA-256 hash of a file or directory.

Parameter Type Required Description
path string yes Absolute path to file or directory

diff_files

Generate a unified diff between two files. Output feeds directly into apply_patch.

Parameter Type Required Description
original string yes Path to original file
modified string yes Path to modified file
context integer no Lines of context in diff output
ignoreWhitespace boolean no Ignore leading/trailing whitespace. Default: false
stripTrailingCr boolean no Strip trailing carriage returns. Default: false

apply_patch

Apply a unified diff patch to one or more files. Single-file: throws on failure. Multi-file: best-effort per file with results[]. Workflow: diff_files -> apply_patch(dryRun) -> apply_patch.

Parameter Type Required Description
path string yes Path to file (single) or base directory (multi-file patch)
patch string yes Unified diff with @@ hunk headers (single or multi-file)
fuzzFactor integer no Max fuzzy mismatches per hunk (0-20)
autoConvertLineEndings boolean no Auto-convert line endings. Default: true
dryRun boolean no Validate without writing. Default: false

search_and_replace

Bulk search-and-replace across files matching a glob. Replaces all occurrences per file. Always dryRun: true first.

Parameter Type Required Description
path string no Base directory (default: root)
filePattern string yes Glob pattern (e.g. **/*.ts)
searchPattern string yes Text to search. RE2 regex when isRegex=true
replacement string yes Replacement text. Supports $1, $2 with regex
isRegex boolean no Treat as RE2 regex. Default: false
dryRun boolean no Preview matches with diff. Default: false
includeHidden boolean no Include dotfiles. Default: false
includeIgnored boolean no Include ignored items. Default: false
returnDiff boolean no Return diff even when not dry-run. Default: false
maxFiles integer no Max files to process before stopping (1-10000)
caseSensitive boolean no Case-sensitive matching. Default: true

Resources

Resource URI MIME Type Description
Instructions internal://instructions text/markdown Comprehensive usage rules and guidelines
Tool Catalog internal://tool-catalog text/markdown Tool selection guide and data flow map
Workflows internal://workflows text/markdown Standard operating procedures for exploration, search, edit, patch
Tool Info internal://tool-info/{name} text/markdown Per-tool contract details, nuances, gotchas
Result Cache filesystem-mcp://result/{id} text/plain Ephemeral cached tool output (large results externalized here)
Metrics filesystem-mcp://metrics application/json Live per-tool call/error/avgDurationMs snapshot

Prompts

Prompt Arguments Description
get-help topic (optional) Return usage instructions. Optionally filter by section heading prefix
compare-files original, modified Generate a workflow for comparing two files using diff_files
analyze-path path Generate a workflow for analyzing a file or directory
get-tool-help name Return a prompt with the authoritative contract for a specific tool

MCP Capabilities

Capability Status Evidence
logging confirmed src/server/bootstrap.ts — registered in capabilities
resources confirmed src/server/bootstrap.ts — 6 resources registered
tools confirmed src/server/bootstrap.ts — 18 tools registered
prompts confirmed src/server/bootstrap.ts — 4 prompts registered
completions confirmed src/completions.ts — path, topic, and tool-name auto-completion
tasks confirmed src/server/bootstrap.ts — optional task support (list, cancel, requests)

Tool Annotations

Annotation Tools Value
readOnlyHint: true roots, ls, find, tree, read, read_many, stat, stat_many, grep, calculate_hash, diff_files Read-only, idempotent, non-destructive
destructiveHint: true write, edit, rm, mv, search_and_replace, apply_patch Destructive writes, not idempotent
idempotentHint: true mkdir Idempotent write, non-destructive

Structured Output

All 18 tools define outputSchema (Zod -> JSON Schema) and return structuredContent alongside text content. Set FS_CONTEXT_STRIP_STRUCTURED=true to strip output schemas from tool definitions (reduces token usage for LLMs that don't use structured output).

Configuration

Variable Default Description
FILESYSTEM_MCP_API_KEY (none) Bearer token required when binding HTTP to a non-loopback host
FILESYSTEM_MCP_MAX_HTTP_SESSIONS 100 Max concurrent HTTP sessions (1-10,000)
FILESYSTEM_MCP_HTTP_HOST 127.0.0.1 HTTP server bind address
FS_CONTEXT_MAX_REQUEST_BYTES 4194304 (4 MB) Max HTTP request body size (1 KB - 256 MB)
FS_CONTEXT_MAX_INLINE_CHARS (auto) Max inline result chars before externalizing to filesystem-mcp://result/{id}
FS_CONTEXT_MAX_INLINE_MATCHES 50 Max inline search matches before truncation
FS_CONTEXT_STRIP_STRUCTURED false Strip outputSchema from tool definitions
FS_CONTEXT_DIAGNOSTICS false Enable diagnostic logging
FS_CONTEXT_DIAGNOSTICS_DETAIL false Enable detailed diagnostic output
FS_CONTEXT_TOOL_LOG_ERRORS false Log tool errors to stderr
FS_CONTEXT_SEARCH_WORKERS_DEBUG false Debug logging for search worker pool

HTTP Endpoints

When started with --port <number>, the server exposes a single MCP endpoint:

Method Path Purpose
POST /mcp Initialize session or send requests (Streamable HTTP)
GET /mcp Server-Sent Events stream for a session
DELETE /mcp Terminate a session

Required headers:

  • mcp-protocol-version — use the negotiated MCP protocol version on post-initialize HTTP requests
  • mcp-session-id — required for GET/DELETE (returned by POST on initialize)

Authentication: Requests to non-loopback HTTP binds require FILESYSTEM_MCP_API_KEY; clients must then send Authorization: Bearer <key>. Loopback-only binds may omit auth for local use. Uses SHA-256 timing-safe comparison.

CORS: Only localhost origins allowed (127.0.0.1, ::1, localhost).

Security

Control Status Evidence
Path sandboxing confirmed src/lib/paths.ts — all paths validated against allowed roots
Traversal prevention confirmed src/lib/paths.ts — resolved paths checked after normalization
Symlink escape prevention confirmed src/__tests__/security.test.ts — symlink boundary enforcement
Sensitive file denylist confirmed src/lib/constants.ts — blocks .git, .env*, SSH keys, certs, secrets
Origin validation confirmed src/server/bootstrap.ts — localhost-only Origin allowlist
Bearer auth confirmed src/server/bootstrap.ts — optional FILESYSTEM_MCP_API_KEY with timing-safe compare
Input validation confirmed src/schemas.ts — Zod strict schemas on all tool inputs
Request body limit confirmed src/server/bootstrap.ts — configurable max request size (413 on overflow)
Remote bind guard confirmed src/server/bootstrap.ts — refuses non-loopback bind without FILESYSTEM_MCP_API_KEY

Development

  • devtsc --watch --preserveWatchOutput — Watch mode TypeScript compilation
  • dev:runnode --env-file=.env --watch dist/index.js — Run server with auto-reload
  • startnode dist/index.js — Run production server
  • buildnode scripts/tasks.mjs build — Clean build
  • testnode scripts/tasks.mjs test — Build + run all tests
  • test:fastnode --test --import tsx/esm src/__tests__/**/*.test.ts node-tests/**/*.test.ts — Run tests without build
  • linteslint . — Lint source
  • type-checknode scripts/tasks.mjs type-check — Type-check src + tests
  • formatprettier --write . — Format code
  • inspectornpm run build && npx -y @modelcontextprotocol/inspector node dist/index.js ${workspaceFolder} — Launch MCP Inspector

Build and Release

  • CI: .github/workflows/release.yml — runs lint, type-check, test, build before tagging/publishing.
  • Docker: Multi-stage build with node:24-alpine. Builder compiles TypeScript + native modules (re2); release stage runs as non-root mcp user.
  • npm: npm run prepublishOnly runs lint + type-check + build.

Troubleshooting

  • "No allowed directories" — Pass at least one directory argument or use --allow-cwd.
  • Sensitive file blocked — Files matching the denylist (.env*, .git, SSH keys) are blocked by design. Check src/lib/constants.ts for the full list.
  • Large result externalized — When tool output exceeds inline limits, it's cached as a resource at filesystem-mcp://result/{id}. Read the resource URI to get the full content.
  • Stdio: logs on stdout — Keep logs on stderr only. The server uses console.error for diagnostics.
  • HTTP 413 — Request body exceeds FS_CONTEXT_MAX_REQUEST_BYTES. Increase the limit or reduce payload size.
  • HTTP 401FILESYSTEM_MCP_API_KEY is set but the request is missing or has an incorrect Authorization: Bearer header.

Credits

Dependency Description
@modelcontextprotocol/sdk MCP TypeScript SDK
commander CLI argument parsing
diff Unified diff generation and patch application
ignore .gitignore pattern matching
re2 Safe RE2 regex engine (no ReDoS)
safe-regex2 Regex safety validation
zod Schema validation and JSON Schema generation

Contributing and License

  • License: MIT
  • Contributions welcome via pull requests.

About

A local filesystem MCP server that lets LLMs and AI agents read, write, search, diff, patch, and manage files safely and efficiently. Built for reliable, structured, and controlled filesystem interaction.

Topics

Resources

Stars

Watchers

Forks

Packages

 
 
 

Contributors