fs-context-mcp-server

j0hanz/fs-context-mcp-server

3.2

If you are the rightful owner of fs-context-mcp-server and would like to certify it and/or have it hosted online, please leave a comment on the right or send an email to dayong@mcphub.com.

A secure Model Context Protocol (MCP) server designed for filesystem scanning, searching, and analysis, built with TypeScript and the official MCP SDK.

Tools
5
Resources
0
Prompts
0

FS Context MCP Server

A read-only MCP server that provides AI assistants with secure filesystem access for exploring, searching, and reading files within approved directories.

npm version Node.js TypeScript MCP SDK

One-Click Install

Install with NPX in VS Code Install with NPX in VS Code Insiders

Install in Cursor

Overview

This server enables AI assistants to navigate your filesystem through a set of read-only tools:

  • Explore directory structures with ls and tree
  • Find files using glob patterns with find
  • Search file contents with grep
  • Read files with options for previews, line ranges, and batch operations
  • Access file metadata through stat and stat_many

All operations are restricted to explicitly approved directories, with no write or modification capabilities.

Features

Directory Operations

  • List directory contents with ls
  • Render directory trees with configurable depth using tree
  • Find files by glob patterns with find

File Operations

  • Read single files with optional line ranges or head preview
  • Batch read up to 100 files in a single operation
  • Get file metadata (size, timestamps, permissions) with stat and stat_many

Search

  • Content search across files using grep
  • Respects .gitignore patterns and common ignore directories
  • Configurable search timeout and worker threads

Security

  • Read-only operations only
  • Access restricted to explicitly approved directories
  • Path traversal protection (blocks .. and symlink escapes)
  • RE2-based regex engine prevents ReDoS attacks

When to Use

TaskTool
Explore project structurels
Render a directory treetree
Find filesfind
Search for code patterns/textgrep
Read source coderead
Batch read multiple filesread_many
Get file metadata (size, dates)stat
Batch get file metadatastat_many
Check available directoriesroots

Quick Start

NPX (Recommended)

For current directory:

npx -y @j0hanz/fs-context-mcp@latest --allow-cwd

For specific projects:

npx -y @j0hanz/fs-context-mcp@latest /path/to/project /path/to/docs

Note: If your MCP client supports the Roots protocol, you can omit directory arguments—the client will provide them automatically.

VS Code

Add to .vscode/mcp.json:

{
  "servers": {
    "fs-context": {
      "command": "npx",
      "args": ["-y", "@j0hanz/fs-context-mcp@latest", "${workspaceFolder}"]
    }
  }
}

Installation

NPX

Run without installation:

npx -y @j0hanz/fs-context-mcp@latest /path/to/dir1 /path/to/dir2

Global Installation

For permanent setup across all projects:

npm install -g @j0hanz/fs-context-mcp
fs-context-mcp /path/to/your/project

From Source

For contributors or custom builds:

git clone https://github.com/j0hanz/fs-context-mcp-server.git
cd fs-context-mcp-server
npm install
npm run build
node dist/index.js /path/to/your/project

Directory Access and Resolution

Access is always restricted to explicitly allowed directories.

  1. CLI directories are validated and added first (if provided).
  2. --allow-cwd optionally adds the current working directory.
  3. MCP Roots from the client are used next:
    • If CLI and/or --allow-cwd are provided, only roots inside those baseline directories are accepted.
    • If no baseline is provided, roots become the allowed directories.
  4. If nothing is configured and the client provides no roots, the server starts with no accessible directories and logs a warning until roots are provided.

Notes:

  • Windows drive-relative paths like C:path are rejected. Use C:\path or C:/path.
  • Reserved Windows device names (e.g., CON, NUL) are blocked.

Configuration

All configuration is optional. Sizes in bytes, timeouts in milliseconds.

Environment Variables

VariableDefaultDescription
MAX_FILE_SIZE10MBMax file size for read operations (range: 1MB-100MB)
MAX_READ_MANY_TOTAL_SIZE512KBMax combined size for read_many (range: 10KB-100MB)
MAX_SEARCH_SIZE1MBMax file size for content search (range: 100KB-10MB)
DEFAULT_SEARCH_TIMEOUT30000Timeout for search/list operations (range: 100-3600000ms)
FS_CONTEXT_SEARCH_WORKERSmin(cpu cores, 8)Search worker threads (range: 0-16; 0 disables)

See for examples and CLI usage.

Resources

This server exposes standard MCP resources to provide static documentation and handle large content efficiently.

Resource URIDescription
internal://instructionsReturns the detailed usage instructions (Markdown) for this server.
fs-context://result/{id}Access to large file content or search results that were truncated in tool outputs.

Note on Large Outputs: Tools like read, read_many, and grep automatically cache content exceeding value limits (default 20k chars). In these cases, the tool returns a preview and a resource_link (URI) that can be read by the client to retrieve the full content.

Tools

All tools return both human-readable text and structured JSON. Structured responses include ok, optional error (with code, message, path, suggestion), plus the tool-specific fields documented below.

roots

List all directories that this server can access.

ParameterTypeRequiredDefaultDescription
(none)----

Returns: Allowed directory paths. Structured output includes ok and directories.


ls

List the immediate contents of a directory (non-recursive). Omit path to use the first allowed root.

ParameterTypeRequiredDefaultDescription
pathstringNofirst rootDirectory path to list (omit to use first root)
includeHiddenbooleanNofalseInclude hidden files and directories

Returns: Entries with name, relativePath, type, size, and modified time. Structured output includes ok, path, entries, and totalEntries.


find

Search for files using glob patterns. Omit path to search from the first allowed root. By default, find excludes common dependency/build directories (node_modules, dist, .git, etc.); set includeIgnored: true to include ignored directories and disable built-in excludes.

ParameterTypeRequiredDefaultDescription
pathstringNofirst rootBase directory to search from (omit to use first root)
patternstringYes-Glob pattern (e.g., **/*.ts, src/**/*.js)
includeIgnoredbooleanNofalseInclude ignored dirs and disable built-in excludes
maxResultsnumberNo100Maximum matches to return (1-10000)

Notes:

  • When includeIgnored=false, results also respect a root .gitignore file (if present under the base path).

Returns: Matching paths (relative) with size and modified date. Structured output includes ok, results, totalMatches, and truncated.


tree

Render a directory tree (bounded recursion). Omit path to use the first allowed root.

  • path (string, optional; default: first root): Base directory to render
  • maxDepth (number, optional; default: 5): Maximum recursion depth (0 = just the root)
  • maxEntries (number, optional; default: 1000): Maximum number of entries before truncating
  • includeHidden (boolean, optional; default: false): Include hidden files/directories
  • includeIgnored (boolean, optional; default: false): Include ignored dirs and disable built-in + .gitignore filtering

Notes:

  • When includeIgnored=false, the tree respects both built-in ignore rules (e.g., node_modules, dist, .git) and a root .gitignore file (if present).

Returns: ASCII tree output plus a structured JSON tree (ok, root, tree, ascii, truncated, totalEntries).


read

Read the contents of a text file.

ParameterTypeRequiredDefaultDescription
pathstringYes-File path to read
headnumberNo-Read only first N lines
startLinenumberNo-1-based start line (inclusive)
endLinenumberNo-1-based end line (inclusive)

Notes:

  • Reads are UTF-8 text only; binary files are rejected.
  • Full reads are capped by MAX_FILE_SIZE (default 10MB). When head is set, output stops at the line limit or size budget, whichever comes first.
  • head cannot be combined with startLine/endLine.
  • If the content exceeds a size limit (default 20k chars), the tool returns a resource_link instead of inline content.

Returns: File content plus structured metadata (ok, path, content, truncated, totalLines, and range metadata when applicable).


read_many

Read multiple files in parallel.

ParameterTypeRequiredDefaultDescription
pathsstring[]Yes-Array of file paths (max 100)
headnumberNo-Read only first N lines of each file
startLinenumberNo-1-based start line (inclusive) per file
endLinenumberNo-1-based end line (inclusive) per file

Notes:

  • Reads files as UTF-8 text; binary files are not filtered. Max size per file is capped by MAX_FILE_SIZE (default 10MB).
  • Total read budget across all files is capped by MAX_READ_MANY_TOTAL_SIZE.
  • No binary detection is performed; use read for single-file safety checks.
  • head cannot be combined with startLine/endLine.
  • If any file content exceeds the inline limit, it is returned as a resource_link.

Returns: Per-file content or error, plus structured summary (total, succeeded, failed).


stat

Get detailed metadata about a file or directory.

ParameterTypeRequiredDefaultDescription
pathstringYes-Path to file or directory

Returns: name, path, type, size, timestamps (created/modified/accessed), permissions, hidden status, MIME type (for files), and symlink target (if applicable). Structured results may include tokenEstimate (rule of thumb: ceil(size/4)).


stat_many

Get metadata for multiple files/directories in parallel.

ParameterTypeRequiredDefaultDescription
pathsstring[]Yes-Array of paths to query (max 100)

Returns: Array of file info with individual success/error status, plus summary (total, succeeded, failed).


grep

Search for text content within files.

  • Omit path to search from the first allowed root.
  • Pass a file path in path to search only that file.

pattern is treated as a literal string and matched case-insensitively.

ParameterTypeRequiredDefaultDescription
pathstringNofirst rootBase directory or file path to search in
patternstringYes-Text pattern to search for
includeHiddenbooleanNofalseInclude hidden files and directories

Example (search a single file):

{ "path": "src/transform.ts", "pattern": "TODO" }

Returns: Matching lines with file path, line number, content, and optional context.

Notes:

  • grep skips binary files by default.
  • Very large files are skipped based on MAX_SEARCH_SIZE (default 1MB). “No matches” is not proof the text is absent from skipped files.

Note: the grep tool currently exposes only path, pattern, and includeHidden. Context fields are omitted unless enabled internally.

Structured output includes ok, matches, totalMatches, and truncated. Matched line content is trimmed to 200 characters.


Built-in exclude list: grep skips common dependency/build/output directories and files: node_modules, dist, build, coverage, .git, .vscode, .idea, .DS_Store, .next, .nuxt, .output, .svelte-kit, .cache, .yarn, jspm_packages, bower_components, out, tmp, .temp, npm-debug.log, yarn-debug.log, yarn-error.log, Thumbs.db.

Error Codes

CodeMeaning
E_ACCESS_DENIEDPath outside allowed roots
E_NOT_FOUNDPath does not exist
E_NOT_FILEExpected file, got directory
E_NOT_DIRECTORYExpected directory, got file
E_TOO_LARGEFile exceeds size limits
E_TIMEOUTOperation timed out
E_INVALID_PATTERNInvalid glob/regex pattern
E_INVALID_INPUTInvalid argument(s)
E_PERMISSION_DENIEDOS-level permission denied
E_SYMLINK_NOT_ALLOWEDSymlink escapes allowed roots
E_UNKNOWNUnexpected error

Client Configuration

VS Code

Add to .vscode/mcp.json (recommended) or .vscode/settings.json:

{
  "servers": {
    "fs-context": {
      "command": "npx",
      "args": ["-y", "@j0hanz/fs-context-mcp@latest", "${workspaceFolder}"]
    }
  }
}
Claude Desktop

macOS: ~/Library/Application Support/Claude/claude_desktop_config.json Windows: %APPDATA%\Claude\claude_desktop_config.json

{
  "mcpServers": {
    "fs-context": {
      "command": "npx",
      "args": ["-y", "@j0hanz/fs-context-mcp@latest", "C:\\path\\to\\project"]
    }
  }
}

If your client supports MCP Roots, you can omit the path. Otherwise, pass a path or --allow-cwd.

Cursor

Add to Cursor's MCP configuration:

{
  "mcpServers": {
    "fs-context": {
      "command": "npx",
      "args": ["-y", "@j0hanz/fs-context-mcp@latest", "${workspaceFolder}"]
    }
  }
}
Codex

Add to ~/.codex/config.toml:

[mcp_servers.fs-context]
command = "npx"
args = ["-y", "@j0hanz/fs-context-mcp@latest", "/path/to/your/project"]

If your client supports MCP Roots, you can omit the path. Otherwise, pass a path or --allow-cwd.

Windsurf

Add to Windsurf's MCP configuration:

{
  "mcpServers": {
    "fs-context": {
      "command": "npx",
      "args": ["-y", "@j0hanz/fs-context-mcp@latest", "${workspaceFolder}"]
    }
  }
}

Security Details

This server implements multiple layers of security:

ProtectionDescription
Access controlOnly explicitly allowed directories are accessible
Path validationAll paths are validated before any filesystem operation
Symlink protectionSymlinks that resolve outside allowed directories are blocked
Path traversal preventionAttempts to escape via .. are detected and blocked
Read-only operationsNo writes, deletes, or modifications
Safe regexRegex validation with RE2 prevents ReDoS
Size limitsConfigurable limits prevent resource exhaustion

Development

Prerequisites

  • Node.js >= 20.0.0
  • npm

Scripts

CommandDescription
npm run buildCompile TypeScript to JavaScript
npm run devWatch mode with tsx
npm run startRun compiled server
npm run testRun tests (node --test with tsx/esm)
npm run test:watchRun tests in watch mode (node --test --watch)
npm run test:coverageRun tests with coverage (node --test --experimental-test-coverage)
npm run test:nodeRun node-tests (isolated checks)
npm run lintRun ESLint
npm run formatFormat code with Prettier
npm run type-checkTypeScript type checking
npm run inspectorTest with MCP Inspector

Project Structure

src/
  index.ts                 # CLI entry point
  server.ts                # MCP server wiring and roots handling
  tools.ts                 # MCP tool registration + response helpers
  schemas.ts               # Zod input/output schemas
  config.ts                # Shared types and formatting helpers
  instructions.md          # Tool usage instructions (bundled in dist)
  lib/                     # Core logic and filesystem operations
  __tests__/               # node:test + tsx tests
node-tests/                # Additional Node.js checks
docs/                      # Static docs assets
dist/                      # Build output (generated)

Troubleshooting

IssueSolution
"Access denied" errorEnsure the path is within an allowed directory. Use roots to check.
"Path does not exist"Verify the path exists. Use ls to explore available files.
"File too large"Use head or increase MAX_FILE_SIZE.
"Binary file" warningread only supports UTF-8 text and rejects binary files.
No directories availablePass explicit paths, use --allow-cwd, or ensure the client provides Roots.
Symlink blockedSymlinks that resolve outside allowed directories are blocked.
Invalid patternSimplify the pattern (note: grep treats pattern as literal text).

Contributing

Contributions are welcome! Please follow these steps:

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/amazing-feature)
  3. Run format, lint, type-check, build, and tests (npm run format && npm run lint && npm run type-check && npm run build && npm run test)
  4. Commit your changes (git commit -m 'Add amazing feature')
  5. Push to the branch (git push origin feature/amazing-feature)
  6. Open a Pull Request

Code Style

  • Use TypeScript with strict mode
  • Follow ESLint configuration
  • Use Prettier for formatting
  • Write tests for new features