Back to Directory/Developer Tools

io.github.j0hanz/filesystem-context

🔍 Read-only MCP server for secure filesystem exploration, searching, and analysis

Developer ToolsTypeScriptv1.0.9

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

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

Docker

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

Or using Docker Compose:

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

CLI Usage

text
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

<details> <summary><b>Install in VS Code</b></summary>

Install in VS Code

Add to .vscode/mcp.json:

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

Or install via CLI:

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

Install in VS Code Insiders

Add to .vscode/mcp.json:

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

Or install via CLI:

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

Install in Cursor

Add to ~/.cursor/mcp.json:

json
{
  "mcpServers": {
    "filesystem": {
      "command": "npx",
      "args": ["-y", "@j0hanz/filesystem-mcp@latest"]
    }
  }
}
</details> <details> <summary><b>Install in Visual Studio</b></summary>

Install in Visual Studio

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

json
{
  "servers": {
    "filesystem": {
      "command": "npx",
      "args": ["-y", "@j0hanz/filesystem-mcp@latest"]
    }
  }
}
</details> <details> <summary><b>Install in Goose</b></summary>

Install in Goose

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

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

Add to LM Studio

json
{
  "mcpServers": {
    "filesystem": {
      "command": "npx",
      "args": ["-y", "@j0hanz/filesystem-mcp@latest"]
    }
  }
}
</details> <details> <summary><b>Install in Claude Desktop</b></summary>

Add to claude_desktop_config.json:

json
{
  "mcpServers": {
    "filesystem": {
      "command": "npx",
      "args": ["-y", "@j0hanz/filesystem-mcp@latest"]
    }
  }
}
</details> <details> <summary><b>Install in Claude Code</b></summary>
sh
claude mcp add filesystem-mcp -- npx -y @j0hanz/filesystem-mcp@latest

Or add a project-scoped .mcp.json:

json
{
  "mcpServers": {
    "filesystem": {
      "command": "npx",
      "args": ["-y", "@j0hanz/filesystem-mcp@latest"]
    }
  }
}
</details> <details> <summary><b>Install in Windsurf</b></summary>

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

json
{
  "mcpServers": {
    "filesystem": {
      "command": "npx",
      "args": ["-y", "@j0hanz/filesystem-mcp@latest"]
    }
  }
}
</details> <details> <summary><b>Install in Amp</b></summary>
sh
amp mcp add filesystem-mcp -- npx -y @j0hanz/filesystem-mcp@latest

Or add to settings.json:

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

Add to cline_mcp_settings.json:

json
{
  "mcpServers": {
    "filesystem": {
      "command": "npx",
      "args": ["-y", "@j0hanz/filesystem-mcp@latest"]
    }
  }
}
</details> <details> <summary><b>Install in Codex</b></summary>
sh
codex mcp add filesystem -- npx -y @j0hanz/filesystem-mcp@latest

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

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

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

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

Add to .kiro/settings/mcp.json:

json
{
  "mcpServers": {
    "filesystem": {
      "command": "npx",
      "args": ["-y", "@j0hanz/filesystem-mcp@latest"]
    }
  }
}
</details> <details> <summary><b>Install in Gemini CLI</b></summary>

Add to ~/.gemini/settings.json:

json
{
  "mcpServers": {
    "filesystem": {
      "command": "npx",
      "args": ["-y", "@j0hanz/filesystem-mcp@latest"]
    }
  }
}
</details> <details> <summary><b>Install in Zed</b></summary>

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

json
{
  "context_servers": {
    "filesystem": {
      "command": "npx",
      "args": ["-y", "@j0hanz/filesystem-mcp@latest"],
      "env": {}
    }
  }
}
</details> <details> <summary><b>Install in Augment</b></summary>

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

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

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

text
[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

text
[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.

ParameterTypeRequiredDescription
pathstringnoBase directory (default: root)
includeHiddenbooleannoInclude dotfiles. Default: false
includeIgnoredbooleannoInclude ignored items (node_modules, .git). Default: false
maxDepthintegernoMax recursion depth (1-100) when pattern is provided
maxEntriesintegernoMax entries before truncation. Default: 1000, Max: 10000
sortByenumnoname | size | modified | type. Default: name
patternstringnoGlob filter (e.g. **/*.ts)
includeSymlinkTargetsbooleannoResolve symlink targets. Default: false
cursorstringnoPagination cursor from a previous response

find

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

ParameterTypeRequiredDescription
pathstringnoBase directory (default: root)
patternstringyesGlob pattern (e.g. **/*.ts)
maxResultsintegernoMax results (1-100000). Default: 1000
includeIgnoredbooleannoInclude ignored items. Default: false
includeHiddenbooleannoInclude dotfiles. Default: false
sortByenumnopath | name | size | modified. Default: path
maxDepthintegernoMax directory depth (0-1000)
cursorstringnoPagination cursor

tree

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

ParameterTypeRequiredDescription
pathstringnoBase directory (default: root)
maxDepthintegernoDepth (0 = root node only). Default: 10, Max: 100
maxEntriesintegernoMax entries. Default: 5000, Max: 100000
includeHiddenbooleannoInclude dotfiles. Default: false
includeIgnoredbooleannoInclude ignored items. Default: false
includeSizesbooleannoInclude file sizes in tree entries. Default: false

read

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

ParameterTypeRequiredDescription
pathstringyesAbsolute path to file
headintegernoRead first N lines (1-100000)
tailintegernoRead last N lines (1-100000)
startLineintegernoStart line (1-based, inclusive)
endLineintegernoEnd line (1-based, inclusive). Requires startLine
includeHashbooleannoInclude SHA-256 hash of full file content. Default: false

read_many

Read multiple text files in one request.

ParameterTypeRequiredDescription
pathsstring[]yesFiles to read (1-100 paths)
headintegernoRead first N lines of each file
tailintegernoRead last N lines of each file
startLineintegernoStart line (1-based) per file
endLineintegernoEnd line (1-based) per file

stat

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

ParameterTypeRequiredDescription
pathstringyesAbsolute path to file or directory

stat_many

Get metadata for multiple files/directories in one request.

ParameterTypeRequiredDescription
pathsstring[]yesFile/directory paths (1-100)

grep

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

ParameterTypeRequiredDescription
pathstringnoBase directory (default: root)
patternstringyesSearch text or RE2 regex when isRegex=true
isRegexbooleannoTreat pattern as RE2 regex. Default: false
caseSensitivebooleannoCase-sensitive matching. Default: false
wholeWordbooleannoMatch whole words only. Default: false
contextLinesintegernoLines of context before/after (0-50). Default: 0
maxResultsintegernoMax match rows (1-100000). Default: 100
filePatternstringnoGlob for candidate files (e.g. **/*.ts)
includeHiddenbooleannoInclude dotfiles. Default: false
includeIgnoredbooleannoInclude ignored items. Default: false

mkdir

Create a new directory (recursive). Idempotent.

ParameterTypeRequiredDescription
pathstringnoAbsolute path to directory to create
pathsstring[]noMultiple directories to create. Either path or paths required

write

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

ParameterTypeRequiredDescription
pathstringyesAbsolute path to file
contentstringyesContent to write

edit

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

ParameterTypeRequiredDescription
pathstringyesAbsolute path to file
editsarrayyesList of {oldText, newText} replacements
dryRunbooleannoPreview edits without writing. Default: false
ignoreWhitespacebooleannoTreat whitespace sequences as equivalent. Default: false

mv

Move or rename a file or directory.

ParameterTypeRequiredDescription
sourcestringnoSingle path to move (deprecated: use sources)
sourcesstring[]noPaths to move. Either source or sources required
destinationstringyesDestination path

rm

Permanently delete a file or directory. Irreversible.

ParameterTypeRequiredDescription
pathstringyesAbsolute path to file or directory
recursivebooleannoDelete non-empty directories. Default: false
ignoreIfNotExistsbooleannoNo error if missing. Default: false

calculate_hash

Calculate SHA-256 hash of a file or directory.

ParameterTypeRequiredDescription
pathstringyesAbsolute path to file or directory

diff_files

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

ParameterTypeRequiredDescription
originalstringyesPath to original file
modifiedstringyesPath to modified file
contextintegernoLines of context in diff output
ignoreWhitespacebooleannoIgnore leading/trailing whitespace. Default: false
stripTrailingCrbooleannoStrip 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.

ParameterTypeRequiredDescription
pathstringyesPath to file (single) or base directory (multi-file patch)
patchstringyesUnified diff with @@ hunk headers (single or multi-file)
fuzzFactorintegernoMax fuzzy mismatches per hunk (0-20)
autoConvertLineEndingsbooleannoAuto-convert line endings. Default: true
dryRunbooleannoValidate 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.

ParameterTypeRequiredDescription
pathstringnoBase directory (default: root)
filePatternstringyesGlob pattern (e.g. **/*.ts)
searchPatternstringyesText to search. RE2 regex when isRegex=true
replacementstringyesReplacement text. Supports $1, $2 with regex
isRegexbooleannoTreat as RE2 regex. Default: false
dryRunbooleannoPreview matches with diff. Default: false
includeHiddenbooleannoInclude dotfiles. Default: false
includeIgnoredbooleannoInclude ignored items. Default: false
returnDiffbooleannoReturn diff even when not dry-run. Default: false
maxFilesintegernoMax files to process before stopping (1-10000)
caseSensitivebooleannoCase-sensitive matching. Default: true

Resources

ResourceURIMIME TypeDescription
Instructionsinternal://instructionstext/markdownComprehensive usage rules and guidelines
Tool Cataloginternal://tool-catalogtext/markdownTool selection guide and data flow map
Workflowsinternal://workflowstext/markdownStandard operating procedures for exploration, search, edit, patch
Tool Infointernal://tool-info/{name}text/markdownPer-tool contract details, nuances, gotchas
Result Cachefilesystem-mcp://result/{id}text/plainEphemeral cached tool output (large results externalized here)
Metricsfilesystem-mcp://metricsapplication/jsonLive per-tool call/error/avgDurationMs snapshot

Prompts

PromptArgumentsDescription
get-helptopic (optional)Return usage instructions. Optionally filter by section heading prefix
compare-filesoriginal, modifiedGenerate a workflow for comparing two files using diff_files
analyze-pathpathGenerate a workflow for analyzing a file or directory
get-tool-helpnameReturn a prompt with the authoritative contract for a specific tool

MCP Capabilities

CapabilityStatusEvidence
loggingconfirmedsrc/server/bootstrap.ts — registered in capabilities
resourcesconfirmedsrc/server/bootstrap.ts — 6 resources registered
toolsconfirmedsrc/server/bootstrap.ts — 18 tools registered
promptsconfirmedsrc/server/bootstrap.ts — 4 prompts registered
completionsconfirmedsrc/completions.ts — path, topic, and tool-name auto-completion
tasksconfirmedsrc/server/bootstrap.ts — optional task support (list, cancel, requests)

Tool Annotations

AnnotationToolsValue
readOnlyHint: trueroots, ls, find, tree, read, read_many, stat, stat_many, grep, calculate_hash, diff_filesRead-only, idempotent, non-destructive
destructiveHint: truewrite, edit, rm, mv, search_and_replace, apply_patchDestructive writes, not idempotent
idempotentHint: truemkdirIdempotent 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

VariableDefaultDescription
FILESYSTEM_MCP_API_KEY(none)Bearer token required when binding HTTP to a non-loopback host
FILESYSTEM_MCP_MAX_HTTP_SESSIONS100Max concurrent HTTP sessions (1-10,000)
FILESYSTEM_MCP_HTTP_HOST127.0.0.1HTTP server bind address
FS_CONTEXT_MAX_REQUEST_BYTES4194304 (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_MATCHES50Max inline search matches before truncation
FS_CONTEXT_STRIP_STRUCTUREDfalseStrip outputSchema from tool definitions
FS_CONTEXT_DIAGNOSTICSfalseEnable diagnostic logging
FS_CONTEXT_DIAGNOSTICS_DETAILfalseEnable detailed diagnostic output
FS_CONTEXT_TOOL_LOG_ERRORSfalseLog tool errors to stderr
FS_CONTEXT_SEARCH_WORKERS_DEBUGfalseDebug logging for search worker pool

HTTP Endpoints

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

MethodPathPurpose
POST/mcpInitialize session or send requests (Streamable HTTP)
GET/mcpServer-Sent Events stream for a session
DELETE/mcpTerminate 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

ControlStatusEvidence
Path sandboxingconfirmedsrc/lib/paths.ts — all paths validated against allowed roots
Traversal preventionconfirmedsrc/lib/paths.ts — resolved paths checked after normalization
Symlink escape preventionconfirmedsrc/__tests__/security.test.ts — symlink boundary enforcement
Sensitive file denylistconfirmedsrc/lib/constants.ts — blocks .git, .env*, SSH keys, certs, secrets
Origin validationconfirmedsrc/server/bootstrap.ts — localhost-only Origin allowlist
Bearer authconfirmedsrc/server/bootstrap.ts — optional FILESYSTEM_MCP_API_KEY with timing-safe compare
Input validationconfirmedsrc/schemas.ts — Zod strict schemas on all tool inputs
Request body limitconfirmedsrc/server/bootstrap.ts — configurable max request size (413 on overflow)
Remote bind guardconfirmedsrc/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

DependencyDescription
@modelcontextprotocol/sdkMCP TypeScript SDK
commanderCLI argument parsing
diffUnified diff generation and patch application
ignore.gitignore pattern matching
re2Safe RE2 regex engine (no ReDoS)
safe-regex2Regex safety validation
zodSchema validation and JSON Schema generation

Contributing and License

  • License: MIT
  • Contributions welcome via pull requests.

Learn More