Skip to main content
Glama
j0hanz

filesystem-mcp

by j0hanz

Filesystem MCP Server

License npm version Build GitHub stars

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

Overview

Filesystem-MCP is a Model Context Protocol server that lets AI assistants read and write files within explicitly allowed directories. Sensitive file patterns (.env, *.pem, *id_rsa*) are blocked by default. It exposes filesystem tools, resources, and prompts over stdio or Streamable HTTP transport.

Aspect

Details

Status

Active (see npm badge for the current version)

Language

TypeScript (strict)

Runtime

Node.js >= 24

Package

npm

License

MIT

Related MCP server: Filesys

Features

Feature

Description

Path guarding

Every path is validated against allowed roots; .env, *.pem, *id_rsa* and similar patterns are denied

Filesystem tools

Navigate, inspect, read, and write across all major file operations

Batch operations

Most tools accept path, paths[], or files[] for parallel execution

Dual transport

stdio by default; --port enables Streamable HTTP

File subscriptions

Resource subscriptions push change notifications when watched files update

Regex safety

RE2 in all search tools: linear-time matching, so no pattern can ReDoS the server

Built with

Node.js TypeScript Docker

Layer

Technology

Protocol

MCP SDK v2 (@modelcontextprotocol/server)

Runtime

Node.js >= 24 · TypeScript 6 · ESM

Transport

stdio (default) · Streamable HTTP (--port)

Regex

RE2 (re2-wasm) — linear time, no lookahead/lookbehind/backreferences

Container

Docker alpine · multi-stage build · non-root user

Table of Contents

Quick start

NOTE

Requires Node.js ≥ 24.

Prerequisites

Requirement

Version / Notes

Node.js

≥ 24

npm

Bundled with Node.js

Docker

Optional — for container use

Install via npx

npx -y @j0hanz/filesystem-mcp /path/to/allowed/dir

Or install globally:

npm install -g @j0hanz/filesystem-mcp
filesystem-mcp /path/to/allowed/dir

Install via Docker

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

Configure in VS Code

Add to .vscode/mcp.json:

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

Or install via CLI:

code --add-mcp '{"name":"filesystem","command":"npx","args":["-y","@j0hanz/filesystem-mcp@latest","/path/to/project"]}'

Configure in Visual Studio

Add to .vs\mcp.json in your solution directory, or %USERPROFILE%\.mcp.json for a global configuration:

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

Configure in Claude Desktop

Add to your claude_desktop_config.json:

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

Install in Cursor

Add to .cursor/mcp.json in your project root (project-scoped), or ~/.cursor/mcp.json for a global configuration:

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

Docker configuration

VS Code (.vscode/mcp.json) and Visual Studio (.vs\mcp.json):

{
  "servers": {
    "filesystem": {
      "command": "docker",
      "args": [
        "run",
        "-i",
        "--rm",
        "-v",
        "/path/to/project:/workspace",
        "ghcr.io/j0hanz/filesystem-mcp:latest",
        "/workspace"
      ]
    }
  }
}

Claude Desktop (claude_desktop_config.json) and Cursor (mcp.json):

{
  "mcpServers": {
    "filesystem": {
      "command": "docker",
      "args": [
        "run",
        "-i",
        "--rm",
        "-v",
        "/path/to/project:/workspace",
        "ghcr.io/j0hanz/filesystem-mcp:latest",
        "/workspace"
      ]
    }
  }
}
NOTE

For least privilege, use both controls::ro makes the container mount read-only at the operating-system boundary, while the server's --read-only flag removes mutating tools (create, edit, move, delete, patch, replace_text) from tools/list.

Usage

Tools

All tools are scoped to the configured roots. Call list_roots first to discover what is allowed.

Navigate

Tool

Description

list_roots

List allowed workspace roots. Call this first — all other tools scope to these.

list

List directory contents. Returns entries (dirs-first, alphabetical) and an ASCII tree.

find_files

Find files by glob pattern (e.g. **/*.ts). Returns matching files with metadata.

Inspect

Tool

Description

stat

Get file/directory metadata: size, modified time, permissions, MIME type, token estimate.

search_text

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

diff

Compare two files and return a unified diff with added/removed line counts.

Read

Tool

Description

read

Read a text file. Supports head/tail and line ranges. Accepts paths[] for batches.

Write

Tool

Description

create

Create one or more files, overwriting existing content and creating parent directories as needed.

edit

Apply sequential literal string replacements to one or more files (max 5 per call).

move

Move, rename, or copy (copy: true) one or more files/directories to explicit destinations.

delete

Permanently delete one or more files or directories. This action is irreversible.

replace_text

Bulk search-and-replace across files matching a glob pattern.

patch

Apply a single-file unified diff and write the result.

Resources

URI

Description

internal://instructions

Server navigation guide — tools overview, constraints, and error recovery.

filesystem-mcp://file/{+path}

Read a workspace file. Subscribe to receive push notifications on change.

filesystem-mcp://result/{id}

Ephemeral cached tool output. Expires after ~60 seconds, eviction, or server restart.

Prompts

Prompt

Description

get-help

Return usage instructions, optionally filtered to a specific section.

Project structure

filesystem-mcp/
├── __tests__/        Test suites
├── scripts/          Build and task utilities
├── src/
│   ├── core/         Path guarding, filesystem abstraction, concurrency, observability
│   ├── tools/        Tool definitions and registration
│   ├── index.ts      Process entrypoint and transport selection
│   ├── server.ts     Server factory and registrar composition
│   ├── transport/    stdio and Streamable HTTP transport setup
│   ├── prompts.ts    Prompt definitions and registration
│   └── resources.ts  Resource definitions and registration
└── Dockerfile        Multi-stage alpine build, non-root user

Runtime composition flows from src/index.ts to src/transport.ts, then to src/server.ts, the registrars, and finally src/core/. Each registrar owns the narrow dependency contract it consumes.

Path

Purpose

src/core/path.ts

PathGuard — validates every path against allowed roots

src/core/fs.ts

GuardedFileSystem — guarded filesystem facade

src/tools/define.ts

Tool registration and execution framework

src/tools/batch.ts

Batch helpers (runOverPaths, normalizeBatchItems)

src/server.ts

Builds shared dependencies and invokes the three registrars

src/transport.ts

Owns stdio and Streamable HTTP setup around the server factory

Configuration

The server starts with allowed directories from explicit startup configuration:

  1. Positional directories passed to filesystem-mcp.

  2. Environment variable FS_ALLOWED_DIRS (separated by : on POSIX or ; on Windows).

  3. Current working directory when --allow-cwd is enabled.

Legacy MCP connections may additionally seed roots through the deprecated roots/list flow. Modern 2026-07-28 connections do not automatically send workspace roots. They can add access after startup by calling a tool with a concrete path and approving the elicitation-backed grant. list_roots reports the roots already configured or accepted; it cannot discover an unknown workspace by itself.

VS Code / Cursor / Claude Code (primary recipe)

Configure the project directory explicitly:

Add to your global or project-scoped configuration:

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

Claude Desktop (fallback recipe via environment variable)

Claude Desktop and similar clients don't support the MCP Roots protocol. Use the FS_ALLOWED_DIRS environment variable to configure allowed folders.

Add to your claude_desktop_config.json:

{
  "mcpServers": {
    "filesystem": {
      "command": "npx",
      "args": ["-y", "@j0hanz/filesystem-mcp@latest"],
      "env": {
        "FS_ALLOWED_DIRS": "/path/to/project1:/path/to/project2"
      }
    }
  }
}

(On Windows, separate directories with a semicolon ; instead of a colon :).

Advanced / per-project positional arguments

You can also restrict access to specific directories by passing positional arguments directly:

# Start with explicit positional paths
filesystem-mcp /path/to/project1 /path/to/project2

Configuration reference

CLI flags

Flag

Default

Purpose

[dirs...]

One or more allowed root directories (positional)

--allow-cwd

false

Also allow the current working directory as a root

--walk-cwd

false

Walk up from CWD to find a project root; implies --allow-cwd

--allow-missing-roots

false

Start even if configured allowed directories do not exist

--port <n>

Enable Streamable HTTP transport on the given port (env: FS_PORT)

--http-host <host>

HTTP server bind address (env: FS_HTTP_HOST)

--api-key <key>

Require this API key on HTTP requests (env: FS_API_KEY)

--read-only

false

Disable write tools: create, edit, delete, move, patch, replace_text

--safe

false

Alias for --read-only

--deny <pattern>

Block paths matching this pattern; repeatable

--allow-sensitive

false

Allow access to sensitive system paths (env: FS_ALLOW_SENSITIVE)

--root-boundary <path>

Require all allowed roots to fall under this path (env: FS_ROOT_BOUNDARY)

--max-file-size <bytes>

Maximum file size for reads in bytes (env: FS_MAX_FILE_SIZE)

--log-level <level>

info

RFC 5424 log level, debug through emergency (env: FS_LOG_LEVEL)

--print-config

false

Print the active configuration and exit (use --json for machine-readable output)

--json

false

Output --print-config as JSON

Environment variables

All boolean variables accept true or 1 to enable and false, 0, or unset to disable; any other value logs a warning and reads as disabled. Flags take precedence when both are set.

Variable

Purpose

FS_ALLOWED_DIRS

Colon-separated (POSIX) or semicolon-separated (Windows) list of directories to allow.

FS_ROOT_BOUNDARY

Path prefix all allowed roots must fall under (mirrors --root-boundary).

FS_ALLOW_CWD_WALK

Walk up from CWD to find a project root (mirrors --walk-cwd).

FS_ALLOW_MISSING_ROOTS

Start even if configured directories do not exist (mirrors --allow-missing-roots).

FS_ALLOW_SENSITIVE

Allow access to sensitive system paths (mirrors --allow-sensitive).

FS_DENYLIST

Comma-separated list of paths or patterns to block (mirrors --deny).

FS_MAX_FILE_SIZE

Maximum file size for reads in bytes (mirrors --max-file-size).

FS_LOG_LEVEL

RFC 5424 log level: debug, info, notice, warn/warning, error, critical, alert, or emergency (mirrors --log-level).

FS_PORT

Start the Streamable HTTP transport on this port; unset = stdio (mirrors --port).

FS_HTTP_HOST

HTTP server bind address (mirrors --http-host).

FS_API_KEY

API key required on HTTP requests (mirrors --api-key).

FS_TRUST_PROXY

Express trust proxy setting: hop count or expression. Unset = do not trust X-Forwarded-*.

FS_ALLOWED_HOSTS

Comma-separated Host header values to accept (HTTP transport).

FS_ALLOWED_ORIGINS

Comma-separated origin hostnames for CORS.

FS_ALLOW_UNRESTRICTED_HOSTS

Bind a wildcard host with no Host validation (accepts the risk).

FS_PUBLIC_URL

Resource identifier URL for RFC 9728 discovery.

FS_RATE_LIMIT_RPM

Per-client-IP requests/minute (default 120 with API-key authentication, 6,000 for keyless loopback; range 1–100000).

FS_MAX_REQUEST_BYTES

Max HTTP request body bytes (default 4194304, 1024–268435456).

FS_KEEPALIVE_TIMEOUT_MS

HTTP keep-alive timeout in ms; set above any fronting proxy's idle timeout (default 5000, 1000–600000).

FS_MAX_WATCHERS

Max concurrent file watchers (default 256, 1–4096).

FS_MAX_INLINE_MATCHES

Max inline content matches per search (default 50, 1–10000).

FS_MAX_READ_MANY_BYTES

Max total bytes across a batched read (default 524288, 10240–104857600).

FS_SEARCH_TIMEOUT_MS

Search timeout in ms (default 5000, 100–60000).

NO_COLOR

Any value disables ANSI color output.

FS_REQUEST_STATE_KEY

HMAC key sealing input_required requestState across retry rounds. Optional for stdio and single-instance HTTP (random per boot if unset); mandatory and shared across every fleet instance (UTF-8, >=32 bytes).

Multi-instance HTTP deployments

Each instance delivers subscriptions/listen change events (resources/updated, tools/list_changed, etc.) on an in-process bus by default. Behind a load balancer with more than one instance, a listener on instance A will not see an event published on instance B. Explicit fleet mode therefore refuses to boot without a shared event bus.

To fan events out across instances, implement the SDK's ServerEventBus interface (two methods: publish/subscribe) over whatever pub/sub you already run, then pass it to filesystem-mcp's programmatic HTTP entry:

import type { ServerEvent, ServerEventBus } from '@modelcontextprotocol/server';

import { startHttpServer } from '@j0hanz/filesystem-mcp/transport';
import Redis from 'ioredis';

// any pub/sub client works the same way

class RedisServerEventBus implements ServerEventBus {
  private readonly listeners = new Set<(event: ServerEvent) => void>();
  private readonly pub = new Redis(process.env['REDIS_URL']);
  private readonly sub = new Redis(process.env['REDIS_URL']);

  constructor() {
    void this.sub.subscribe('fs-mcp-events');
    this.sub.on('message', (_channel, message) => {
      const event = JSON.parse(message) as ServerEvent;
      for (const listener of this.listeners) listener(event);
    });
  }

  publish(event: ServerEvent): void {
    void this.pub.publish('fs-mcp-events', JSON.stringify(event));
  }

  subscribe(listener: (event: ServerEvent) => void): () => void {
    this.listeners.add(listener);
    return () => this.listeners.delete(listener);
  }
}

const eventBus = new RedisServerEventBus();
const apiKey = process.env['FS_API_KEY'];
if (!apiKey) throw new Error('FS_API_KEY is required for a multi-instance HTTP deployment');

await startHttpServer(
  3000,
  { cliAllowedDirs: ['/workspace'] },
  { apiKey, eventBus, deploymentMode: 'fleet' },
);

This project ships no bus adapter and no pub/sub dependency. A single in-process instance (the common case) needs nothing extra and is the CLI's default. Load-balanced deployments must use the programmatic API with deploymentMode: 'fleet'.

Examples

# Allow current working directory
filesystem-mcp --allow-cwd

# HTTP transport on port 3000
filesystem-mcp --port 3000

Scripts

Mode

Command

Description

Full check

node scripts/tasks.mjs

Run build, type check, lint, format, knip, and tests

Auto-fix + check

node scripts/tasks.mjs fix

Auto-fix formatting/linting and run the full check

Static only

node scripts/tasks.mjs --quick

Run static analysis without tests

Tests only

node scripts/tasks.mjs test

Run tests; accepts native node --test options

Security

IMPORTANT

Report vulnerabilities privately viaGitHub Security Advisories. Do not open public issues for security reports.

Topic

Detail

Path traversal

Every path is resolved and validated against allowed roots before any operation

Sensitive files

.env, *.pem, *id_rsa*, and similar patterns are denied by default

Regex safety

RE2 cannot backtrack, so a hostile pattern cannot hang the server (ReDoS)

Container

Runs as non-root mcp user; bind mounts control what is exposed

Contributing

  1. Fork the repository.

  2. Create a feature branch: git checkout -b feat/your-feature.

  3. Commit your changes with a clear message.

  4. Run node scripts/tasks.mjs to confirm tests, types, lint, formatting, and knip all pass.

  5. Open a pull request.

Contributors

License

Released under the MIT License. See LICENSE for details.

Available Tools

13 tools
createCreate FilesA
Destructive

Create one or more files (max 100), writing or overwriting content and creating parent directories as needed. Pass files: [{ path, content }] — there is no single-path form. Silently overwrites existing files — read first if you need to preserve existing content.

ParametersJSON Schema
NameRequiredDescriptionDefault
filesYesList of files to create (max 100); each entry requires path and content

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the destructiveHint and readOnlyHint annotations, the description discloses additional key behaviors: it creates parent directories, silently overwrites existing files, enforces a 100-file limit, and has no single-path convenience form. This gives the agent a full safety picture.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three sentences, each earning its place: what the tool does, the exact input shape, and the overwrite warning. The most important constraint is front-loaded and there is no redundant filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple tool with one parameter, no output schema, and no nested objects, the description covers invocation shape, limits, side effects, and safety guidance. An agent has everything needed to call it correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema already documents files, path, and content well, so the baseline is 3. The description adds real value by stating the exact required array shape 'files: [{ path, content }]' and explicitly ruling out a single-path invocation, which helps avoid incorrect calls.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states a specific action (create one or more files) and resource (files with path/content), and distinguishes the batch-only shape with 'there is no single-path form.' It is easy to tell apart from siblings like edit, patch, and delete.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides clear context: use this to create files, and know that it overwrites existing content. It advises reading first when preservation matters, though it does not explicitly contrast with alternatives like edit or patch for modifying existing files.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

deleteDelete FileA
Destructive

Permanently delete one or more files, directories, or symlinks (max 1000 per call). This action is irreversible. Pass paths: [...] — there is no single-path form. Non-empty directories require recursive=true and additionally prompt the user to confirm each one, so the call returns without deleting anything until that confirmation comes back; a client that cannot prompt gets an error naming the alternative. Workspace root directories cannot be deleted.

ParametersJSON Schema
NameRequiredDescriptionDefault
pathsYesPaths to delete (max 1000); accepts files, directories, or symlinks
recursiveNoDelete directory contents recursively (required for non-empty directories)
ignoreIfNotExistsNoSilently succeed if a path does not exist instead of returning an error

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultsYesPer-path results ordered to match the input paths
summaryYes

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already say destructiveHint=true, and the description goes well beyond that by disclosing irreversibility, the confirmation mechanism that makes calls return without deleting, the error behavior for clients that cannot prompt, and the workspace-root safeguard. This is rich, actionable behavioral context.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is dense but every sentence contributes: scope, irreversibility, path form, recursive behavior, prompting caveat, and root restrictions. It is slightly long due to the confirmation explanation, but that complexity is necessary and not wasted.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a destructive tool with three simple parameters and an output schema, the description covers the critical call-time facts: limits, required flags, interaction behavior, irreversibility, and an explicit prohibition. An agent has enough to call this correctly and safely.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% and schema already documents all three parameters. The description adds useful meaning by emphasizing that paths must be passed as an array, that there is no single-path form, and that recursive=true triggers per-directory confirmation. It does not delve into ignoreIfNotExists, but the schema handles that parameter well.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The first sentence clearly states the action ('permanently delete') and the exact resources affected (files, directories, symlinks). It is unambiguous and distinguishes this from the sibling create, edit, and move operations.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives clear operational context: the 1000-item cap, the need for recursive=true on non-empty directories, the interactive confirmation requirement, and the workspace-root restriction. It does not explicitly name an alternative tool to use instead, but the conditions for safe use are well specified.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

diffDiffA
Read-only

Compare two files and return a unified diff with line counts. Pass the two paths as a and b. Use after an edit dry-run to compare against another file, or to inspect changes between two paths.

ParametersJSON Schema
NameRequiredDescriptionDefault
aYesFirst file to compare
bYesSecond file to compare
contextNoNumber of context lines surrounding each change (default: 3)

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and openWorldHint=false, so the safety profile is covered. The description adds useful behavioral detail by specifying that the result is a unified diff with line counts, which an agent would not otherwise know.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two short sentences with no filler. The first sentence states the core purpose and output; the second gives practical usage guidance. Every part earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple read-only comparison tool, the description plus the high-coverage schema and readOnly/openWorld annotations are complete. It explains what to pass, what is returned, and when to use it. An agent has enough to invoke it correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the parameters a, b, and context are already fully documented in the schema. The description adds minimal extra semantic value beyond restating that a and b are the two paths.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb ('Compare'), a clear resource ('two files'), and the output format ('unified diff with line counts'). This is distinct from the sibling tools, which perform creation, editing, reading, or searching — not file comparison.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives explicit use cases: after an edit dry-run to compare against another file, or to inspect changes between two paths. It does not mention when not to use it or name an alternative, but the provided context is clear enough for an agent.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

editEdit FilesA
Destructive

Apply sequential literal string replacements to one or more files (max 5 files per call). Modes: single-file { path, edits } or per-file { files: [{ path, edits }] }. oldText must match file content exactly; include 3-5 lines of surrounding context to ensure uniqueness. Set dryRun=true to preview diffs without writing. For glob-based bulk regex replacement across many files, use replace_text instead.

ParametersJSON Schema
NameRequiredDescriptionDefault
pathNoSingle file path; mutually exclusive with files
editsNoReplacements applied to path; not allowed when using files
filesNoPer-file entries (batch mode)
dryRunNoPreview diffs without writing to disk (default: false = apply edits)
ignoreWhitespaceNoIgnore leading/trailing whitespace differences when matching oldText

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultsYesPer-path edit results ordered to match the input paths
summaryYes

TDQS

A4.7/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The annotations already declare destructiveHint=true and readOnlyHint=false, and the description reinforces that writes occur by contrasting dryRun. It adds useful operational detail: edits are sequential, literal, limited to 5 files per call, and require exact matches with context. It could further state failure behavior when oldText is not found, but the key behavioral traits are disclosed.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three dense sentences cover purpose, modes, matching requirements, dry-run usage, and the key alternative. The most important constraint is front-loaded, and every sentence earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the output schema and full parameter descriptions, the tool definition leaves no critical gap: modes, limits, matching behavior, dry-run previews, and the intended alternative are all covered. An agent has enough information to decide when to invoke edit and how to formulate a safe call.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the baseline is 3. The description goes beyond the schema by clarifying that replacements are applied sequentially, explaining the two call modes, and reinforcing the 5-file cap and exact-match requirement.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description starts with a precise verb and object: 'Apply sequential literal string replacements to one or more files.' It clearly distinguishes this tool from replace_text, which handles glob-based bulk regex replacement, so an agent can tell them apart immediately.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives an explicit routing rule: use replace_text for glob-based bulk regex across many files. It also directs users to dryRun=true for previewing diffs, clarifying the safe way to test edits before applying them.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

find_filesFind FilesA
Read-only

Find files matching a glob pattern. Returns matched paths with optional metadata. Pagination cursors reference a query-bound snapshot that expires after 60 seconds. For content search use search_text; for bulk regex replacements use replace_text with the same glob.

ParametersJSON Schema
NameRequiredDescriptionDefault
pathNoBase directory to search under (default: first allowed root)
cursorNoOpaque pagination cursor; pass unchanged for the next page. Pages slice one snapshot taken on the first call; it expires after ~60s — re-request without a cursor if rejected.
sortByNoSort order: path = full path (default), name = basename onlypath
patternYesGlob pattern to match file paths (e.g. **/*.ts, src/**/*.js)
maxDepthNoMax directory depth to scan; 0 = base directory only, omit for unlimited
maxResultsNoMaximum number of matching files to return per page
includeHiddenNoInclude hidden items (starting with .)
includeIgnoredNoInclude ignored items (node_modules, .git, etc).

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and openWorldHint=false, so the safety profile is covered. The description adds value by disclosing the query-bound snapshot semantics and 60-second expiry for pagination cursors, which is behavioral context beyond the structured fields. No contradiction with annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three sentences, each earning its place: purpose and return shape, pagination snapshot behavior, and sibling routing. Zero filler, and the core purpose is front-loaded before secondary details.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For an 8-parameter tool with 100% schema coverage, the description covers the essentials: purpose, return shape ('matched paths with optional metadata'), pagination semantics, and alternatives. No output schema exists, but the description gives a reasonable return-shape hint. Slightly more detail on return format would push it to a 5, but nothing critical is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the schema fully documents all 8 parameters with examples (e.g., '**/*.ts') and defaults. The description adds no parameter-level detail beyond what the schema provides; the baseline of 3 applies since the schema does the heavy lifting.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('find files matching a glob pattern') with a clear scope. It also names the siblings it is not (search_text for content, replace_text for regex replacement), so an agent can distinguish it from the most confusable tools without opening schemas.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly routes to alternatives: 'For content search use search_text; for bulk regex replacements use replace_text with the same glob.' This tells the agent exactly when not to use this tool and which sibling to pick instead.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

listListB
Read-only

List sorted directory entries and an ASCII tree. maxDepth=1 is top-level. maxEntries sets page size; continue with nextCursor. resourceUri is only for hard-cap overflow.

ParametersJSON Schema
NameRequiredDescriptionDefault
pathNoDirectory to list (default: first allowed root)
cursorNoOpaque pagination cursor; pass unchanged for the next page. Pages slice one snapshot taken on the first call; it expires after ~60s — re-request without a cursor if rejected.
maxDepthNoMax directory depth to traverse (default: 1 = top-level only; increase to recurse deeper)
maxEntriesNoPage size (default: 1000). Continue with nextCursor; resourceUri is only for hard-cap overflow.
includeHiddenNoInclude hidden items (starting with .)
includeIgnoredNoInclude ignored items (node_modules, .git, etc).

TDQS

B3.4/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and openWorldHint=false, so the safety profile is covered. The description adds behavioral details such as the ASCII tree output, sorting, and the pagination mechanism ('continue with nextCursor'). However, it omits details like snapshot expiration (which is only in the cursor schema) and does not fully describe output format, keeping it at an average level.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single, tightly packed sentence with a clear front-loaded purpose. It avoids redundancy and every clause adds value, efficiently conveying the core function and key parameter behaviors without fluff.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a tool with no output schema and six fully documented parameters, the description provides adequate but not exhaustive context. It explains the main behavioral aspects (tree structure, pagination) but does not describe the output format or error handling. Given the tool's simplicity and the rich schema, this is minimally sufficient but leaves room for more detail.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3. The description adds extra semantic context beyond the schema by explaining maxDepth semantics ('maxDepth=1 is top-level') and pagination behavior ('maxEntries sets page size; continue with nextCursor'), including a note about 'resourceUri' for hard-cap overflow, which enriches parameter understanding.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states a specific action ('List') and the resource ('sorted directory entries and an ASCII tree'), going beyond a tautology. It provides useful keywords like 'sorted' and 'ASCII tree' that help distinguish the tool from others like find_files, though it does not explicitly contrast them.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description offers parameter-level guidance (e.g., 'maxDepth=1 is top-level', 'maxEntries sets page size') but does not explain when to use this tool versus its siblings (e.g., find_files, search_text). There is no mention of exclusions or alternatives, leaving the agent to infer the appropriate context.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_rootsWorkspace RootsA
Read-only

List the allowed workspace root directories. Call this first to discover what paths are accessible; all other tools are scoped to these roots. Allowed directories are configured via CLI arguments, the FS_ALLOWED_DIRS environment variable, or --allow-cwd.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A4.7/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already establish readOnlyHint=true, and the description adds meaningful context beyond that: it explains where the allowed directories come from (CLI arguments, FS_ALLOWED_DIRS, --allow-cwd). This gives the agent useful operational knowledge about the tool's behavior and configuration without contradicting the annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three tight sentences, each earning its place: the primary action, the critical usage instruction, and the configuration sources. The most important information is front-loaded in the first sentence.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a parameterless, read-only listing tool, this is complete. It tells the agent when to call it, what it returns conceptually (accessible paths), and how those roots are configured. No output schema exists, but the description sufficiently implies a list of path strings.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool takes zero parameters and the schema is empty, so there is nothing for the description to document. The baseline for 0 params is 4, and the description appropriately avoids inventing parameter details, keeping the tool's parameterless nature clear.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb ('List') and a specific resource ('allowed workspace root directories'), and immediately clarifies how it differs from the file-operation siblings: every other tool is scoped to these roots. An agent can distinguish list_roots from the generic 'list' sibling without opening schemas.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly instructs the agent to 'Call this first' and explains why — the results determine which paths are accessible to all other tools. This is clear, actionable usage guidance that leaves no ambiguity about when this tool should be invoked.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

moveMove or Copy FilesA
Destructive

Move, rename, or copy files and directories to explicit destination paths (max 100 operations per call). Pass moves: [{ source, destination }] — there is no single-pair form. Parent directories are created automatically. Set copy=true to copy instead of move (sources are kept). An existing destination prompts the user to confirm the overwrite, so the call returns without moving anything until that confirmation comes back; copy=true with overwrite=true skips the prompt, move has no such bypass. Self-moves are silently skipped.

ParametersJSON Schema
NameRequiredDescriptionDefault
copyNoCopy instead of move; sources are left in place
movesYesOperations to perform (max 100)
overwriteNoCopy mode only: overwrite existing destinations without confirmation

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Given destructiveHint is already true, the description adds substantial behavioral context: parent directories are created automatically, existing destinations trigger a confirmation that causes the call to return without moving anything, overwrite bypass exists only in copy mode, and self-moves are silently skipped. This goes well beyond the annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is dense but every sentence earns its place. It front-loads purpose, then gives the input form, then explains edge-case behaviors. No filler or repetition of schema details.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The description covers the operation limit, required array form, destination handling, parent directory creation, copy semantics, overwrite confirmation, and self-move behavior. For a tool without an output schema, this provides ample context for correct invocation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the schema already documents all parameters. The description adds meaning beyond the schema by clarifying the exact call shape ('Pass moves: [{ source, destination }]') and emphasizing that there is no single-pair form, plus the effect of copy and overwrite on runtime behavior.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description begins with a specific verb and resource: 'Move, rename, or copy files and directories to explicit destination paths.' This clearly distinguishes the tool from siblings like create, delete, and edit, while also noting the 100-operation limit.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives clear context for use: pass an array of move pairs, there is no single-pair form, and copy=true switches to copy mode. It does not explicitly state when not to use this tool versus siblings like edit or delete, but the intended use is strongly implied by the tool's purpose.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

patchPatchA
Destructive

Apply a single-file unified diff to one file and write the result. Pass { path, diff }. Use after inspecting a diff tool dry-run: pass the diff blob directly instead of re-expressing it as line edits. Rejects multi-file diffs and diffs whose hunk context does not match the file. Set dryRun=true to preview the result without writing.

ParametersJSON Schema
NameRequiredDescriptionDefault
diffYesSingle-file unified diff to apply (as produced by the diff tool or edit dry-run)
pathYesFile to apply the diff to
dryRunNoPreview the result without writing (default: false)

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the destructiveHint annotation, the description discloses that the tool writes to a file, supports dryRun=true to preview without writing, and rejects multi-file diffs or diffs whose hunk context does not match. These are meaningful behavioral constraints that help the agent anticipate failures.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three tight sentences front-load the core purpose, then provide usage context, constraints, and the dryRun option. No filler or redundant explanation; every sentence earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The description covers the required inputs, the key failure modes, and the safety dryRun option. Even without an output schema, an agent has enough information to invoke this tool correctly and to avoid common misuse.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents path, diff, and dryRun. The description adds little beyond restating 'Pass { path, diff }' and the dryRun preview behavior, which is already in the schema. Baseline 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific action ('Apply a single-file unified diff'), the target resource ('to one file'), and the outcome ('write the result'). It also distinguishes itself from line-edit workflows by explicitly saying the diff blob should be passed directly, so an agent can differentiate this from sibling edit tools.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives explicit when-to-use guidance: after inspecting a diff-tool dry-run. It also gives a clear when-not-to-use signal by saying 'instead of re-expressing it as line edits', and it describes rejection conditions for multi-file and mismatched diffs.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

readRead FileA
Read-only

Read one or more text files and return content. Partial reads: head (first N lines), tail (last N lines), startLine/endLine (line range). Batch mode: pass paths[] instead of path; line params are shared across all files. head, tail, and startLine/endLine are mutually exclusive — use exactly one.

ParametersJSON Schema
NameRequiredDescriptionDefault
headNoReturn first N lines
pathNoSingle file path; mutually exclusive with paths
tailNoReturn last N lines
pathsNoArray of file paths for batch mode (max 1000); mutually exclusive with path
endLineNoEnd line (1-indexed)
startLineNoStart line (1-indexed)
includeHashNoInclude SHA-256 hash of the returned content in the response

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultsYesPer-path results ordered to match the input paths
summaryYes

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already carry read-only and closed-world hints; the description adds valuable behavioral details on partial reads, batch-mode parameter sharing, and mutual exclusivity of head/tail/line-range options. It does not cover edge cases like missing files or directory input, but the core behavior is transparent.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three sentences with zero fluff. The action is front-loaded, partial-read modes are listed compactly, and the batch-mode rule and mutual-exclusivity constraint are stated in a single final sentence. Every sentence earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a tool with a rich schema, read-only annotations, and an output schema, the description is nearly complete: it covers modes, parameter sharing, and exclusivity. It omits only minor edge-case behavior such as missing-file or directory-handling semantics, which are not critical for correct invocation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

All 7 parameters are documented in the schema (100% coverage), so the baseline is 3. The description adds semantics beyond the schema: line parameters are shared across files in batch mode, and head/tail/startLine-endLine are mutually exclusive. That grouping and relationship information justifies a 4.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a precise verb+resource ('Read one or more text files and return content') that unambiguously separates it from sibling tools like list, stat, and search_text. The action is inherently distinct, so no explicit sibling naming is needed.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The first sentence establishes the core use case (reading text file content), and the description gives clear context for partial reads and batch mode. However, it does not explicitly contrast with sibling tools or state when not to use read, so no exclusions are provided.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

replace_textSearch and ReplaceA
Destructive

Bulk search-and-replace across files matching a glob pattern. Replaces ALL occurrences per file (unlike edit, which replaces only the first match). Set returnDiff=true to preview changes as a unified diff before or after writing. Literal matching by default; set isRegex=true to enable RE2 regex with capture groups ($1, $2).

ParametersJSON Schema
NameRequiredDescriptionDefault
pathNoFile to rewrite, or directory to rewrite under. Omitting it targets the ENTIRE first allowed root — scope it deliberately, and pair a wide scope with dryRun=true first
dryRunNoPreview replacements without writing to disk (default: false = apply changes)
isRegexNoTreat searchPattern as a RE2 regex (default: literal text match)
patternNoGlob to restrict replacements to specific file types (e.g. **/*.ts); default: all text files
maxDepthNoMax directory depth to scan; 0 = base directory only, omit for unlimited
maxFilesNoMaximum number of files to process
wholeWordNoMatch whole words only (word boundary anchoring)
maxResultsNoMaximum total match count across all files before stopping
returnDiffNoInclude a unified diff of all changes in the response
replacementYesReplacement text. Use capture group references ($1, $2, etc.) when isRegex=true. Use an empty string to delete all matches.
caseSensitiveNoEnable case-sensitive matching (default: case-insensitive)
includeHiddenNoInclude hidden items (starting with .)
searchPatternYesExact literal text or RE2 regex pattern to search for. When isRegex=true, uses RE2 syntax (no lookahead, lookbehind, or backreferences are supported). Cannot be empty or whitespace-only.
includeIgnoredNoInclude ignored items (node_modules, .git, etc).

Output Schema

ParametersJSON Schema
NameRequiredDescription
diffNoUnified diff of all changes (present when returnDiff=true or dryRun=true)
resultsYesPer-file results: modified files, then any that could not be processed
summaryYes
filesScannedYesTotal number of files examined
totalMatchesYesTotal number of replacements made across all files
diffTruncatedNoTrue when the diff was cut due to the size limit
stoppedReasonNoWhy enumeration stopped early: maxResults = match cap reached, maxFiles = file cap reached, timeout = time limit hit or cancelled. Absent when every matching file was enumerated. Marks the sweep incomplete, not the writes; files already dispatched still complete.
resultsTruncatedNoTrue when the results list holds fewer entries than summary.total: the changed-file or failed-file cap was hit. Trust summary over results.length.

TDQS

A4.6/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations declare `destructiveHint: true`, and the description strengthens this by stating that replacements are written and that `returnDiff` can preview changes before or after writing. It also discloses default literal matching and RE2 regex behavior. It could add more about dry-run usage, but the description already goes beyond the annotations usefully.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three compact sentences front-load the core purpose, the key distinction from `edit`, the preview mechanism, and the regex/literal behavior. Every sentence contributes meaning and there is no redundant restatement of schema or annotations.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a destructive bulk-operation tool with 14 parameters, the description efficiently covers the essential decision points and safety mechanism. The comprehensive schema and output schema cover the remaining parameters and return shape. A direct mention of `dryRun` in the description would make it slightly more complete, but the existing guidance via `returnDiff` and the `path` schema is strong.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the schema already documents all parameters. The description adds value by explaining tool-level semantics: literal vs. regex matching, capture-group references, all-occurrence replacement, and diff previews. This clarifies how the core parameters interact without replacing the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly identifies the action ('Bulk search-and-replace'), the resource ('files matching a glob pattern'), and the key behavioral scope ('Replaces ALL occurrences per file'). It also explicitly contrasts itself with the sibling `edit`, so an agent immediately knows how this tool differs.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It provides an explicit alternative and the deciding condition: use this tool for all occurrences, whereas `edit` replaces only the first match. It also gives concrete guidance on when to enable `returnDiff` for previewing changes, helping agents choose safe invocation patterns.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

search_textSearch ContentA
Read-only

Search file contents by text or regex (grep-style). Returns matching lines with file path, 1-indexed line number and 0-indexed column offset. Scope to specific file types with pattern (e.g. **/*.ts). Set includeHidden=true to include dotfiles. Use find_files to search by filename instead.

ParametersJSON Schema
NameRequiredDescriptionDefault
pathNoFile to search, or directory to search under (default: the whole first allowed root). Naming a file searches that file alone: pattern is ignored and hidden/ignored filtering does not apply.
cursorNoOpaque pagination cursor; pass unchanged for the next page. Pages slice one snapshot taken on the first call; it expires after ~60s — re-request without a cursor if rejected.
isRegexNoTreat searchPattern as a regex (default: literal text match)
patternNoGlob to restrict search to specific file types (e.g. **/*.ts); default: all text files
maxDepthNoMax directory depth to scan; 0 = base directory only, omit for unlimited
maxResultsNoMaximum number of matching lines to return per page
caseSensitiveNoEnable case-sensitive matching (default: case-insensitive)
includeHiddenNoInclude hidden items (starting with .)
searchPatternYesExact literal text or RE2 regex pattern to search for in file contents. When isRegex=true, uses RE2 syntax (no lookahead, lookbehind, or backreferences). Cannot be empty or whitespace-only.
includeIgnoredNoInclude ignored items (node_modules, .git, etc).

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The annotations already declare readOnlyHint=true, so the read-only safety profile is covered. The description adds meaningful behavioral context beyond the annotations: it discloses the return format (matching lines with file path, 1-indexed line number, 0-indexed column offset) and highlights grep-style semantics. It does not mention pagination or snapshot behavior, but those are documented in the schema's cursor parameter, so the extra context is sufficient.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Every sentence earns its place: the first states the core function, the second describes the output format, the third explains scoping, the fourth covers hidden files, and the fifth routes to the correct sibling. It is front-loaded and contains no filler or redundant fluff.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the rich input schema (100% coverage across all 10 parameters) and the absence of an output schema, the description adequately fills the remaining gap by specifying the return format. It also covers the key searching behaviors (regex/literal, hidden files, glob scoping) and points to the alternative for filename search. An agent has enough to select and invoke this tool correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the baseline is 3. The description reinforces the meaning of 'pattern' with an example and explains includeHidden's effect, but it largely repeats what the schema already provides. It adds value for output semantics rather than parameter semantics, so a 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb and resource ('Search file contents'), states the method (text or regex, grep-style), and immediately distinguishes itself from the sibling find_files ('search by filename instead'). An agent can tell exactly what this tool does and how it differs from nearby tools without inspecting the schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It explicitly names the alternative tool (find_files) and the exact condition that selects it (searching by filename instead of content). It also gives practical usage tips such as scoping with a glob pattern and enabling includeHidden for dotfiles, giving the agent clear guidance on when and how to use the tool.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

statGet File InfoA
Read-only

Get metadata for one or more files or directories: size, type, permissions, MIME type, timestamps, and tokenEstimate. Use tokenEstimate to pre-screen read cost before calling read. Single path: pass path. Batch mode: pass paths[].

ParametersJSON Schema
NameRequiredDescriptionDefault
pathNoSingle file path; mutually exclusive with paths
pathsNoArray of file paths for batch mode (max 1000); mutually exclusive with path

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true, so the safe read-only nature is established outside the description. The description adds useful behavioral context with tokenEstimate as a cost pre-screening signal and lists the metadata categories returned, though it does not detail batch response shape or error behavior.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is three tight sentences: the first states what the tool returns, the second gives the key workflow rationale, and the third covers parameter mode selection. Every sentence earns its place with no repetition or filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple, read-only stat tool, the description is nearly complete: it lists return fields, explains tokenEstimate utility, and covers both invocation modes. The main gap is that without an output schema, it does not specify the exact response structure for batch calls, but the enumerated fields mitigate this.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already fully documents path and paths, including mutual exclusivity and the 1000-item limit. The description only restates 'Single path: pass path. Batch mode: pass paths[]', adding little beyond the structured schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb and resource: 'Get metadata for one or more files or directories' and enumerates the returned fields (size, type, permissions, MIME type, timestamps, tokenEstimate). This clearly distinguishes it from siblings like read (content access) and list (directory enumeration).

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It explicitly says to use tokenEstimate to pre-screen read cost before calling read, naming the alternative tool and the exact condition that selects stat. It also clarifies single-path vs batch-mode usage, giving practical selection guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

TDQS

A4.1/5.0
Disambiguation4/5

Most tools map to a distinct operation (read vs stat vs list, search_text vs find_files), but content modification is split across edit, replace_text, and patch with overlapping capabilities. The descriptions are detailed enough to guide selection, though the overlap creates some misselection risk.

Naming Consistency3/5

The set mixes bare single-word verbs (create, read, list, stat) with snake_case verb_noun commands (replace_text, list_roots, search_text, find_files). All names are lowercase imperatives, so the set is readable, but the pattern is not uniform enough for high consistency.

Tool Count5/5

Thirteen tools is well within the appropriate range for a general filesystem server. Each tool addresses a distinct area such as writing, reading, editing, searching, navigating, moving, copying, deleting, and metadata inspection without obvious redundancy.

Completeness4/5

The surface covers the core file lifecycle: create, read, update, move/copy, delete, list, search, and metadata. Minor gaps exist around explicit empty-directory creation and permission/symlink management, but these are workaround-able and do not create dead ends.

Maintenance

ActivityActive
ResponsivenessSyncing

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Connectors

Related MCP Servers

  • -
    license
    Not graded
    quality
    Not graded
    maintenance
    A Filesystem MCP server that allows an LLM to read and list files from a specified directory on your local machine through the Model Context Protocol.
    2
  • F
    license
    Not graded
    quality
    D
    maintenance
    MCP server providing filesystem operations, shell execution, and web search capabilities.
  • A
    license
    Not graded
    quality
    C
    maintenance
    Experimental MCP server for local LLM orchestration with filesystem tools (read, write, list, delete files) and a CLI agent that communicates via Ollama.
    12
    ISC

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/j0hanz/filesystem-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server