Skip to main content
Glama

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 for both 2025-era and 2026-07-28 clients

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, creating parent directories as needed. An existing file prompts the user to confirm the overwrite; overwrite: true on an entry skips the prompt, append: true adds to the end instead.

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
├── 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, isTotalFailure)

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.

Over HTTP, 2025-era clients are served statelessly: tools, resources and prompts work. Confirmations (recursive delete, overwrite, access grants) need a 2026-07-28 client or stdio and answer with a tool error saying so; file subscriptions are not advertised on that leg, and a resources/subscribe sent anyway is refused with method-not-found.

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

--deny <pattern>

Block paths matching this pattern; repeatable

--allow <pattern>

Exempt a pattern from the built-in sensitive denylist; repeatable (env: FS_ALLOWLIST). Does not lift --deny/FS_DENYLIST entries

--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 as JSON and exit

--deny and --allow patterns support * (any run within a segment), ** (any run of segments), ?, [...] classes, and {a,b} alternation. Dot-leading (hidden) names match like any other — secrets/** denies secrets/.env, *id_rsa* denies .id_rsa.

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_ALLOWLIST

Comma-separated patterns exempted from the built-in sensitive denylist (mirrors --allow). Never lifts FS_DENYLIST/--deny entries.

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_WATCHERS

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

NO_COLOR

Any value disables ANSI color output.

FS_REQUEST_STATE_KEY

HMAC key sealing input_required requestState across retry rounds. Optional (random per boot if unset); set it, at >=32 bytes UTF-8, to keep in-flight rounds alive across a restart.

Examples

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

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

Scripts

Mode

Command

Description

Full check

npm run check

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

Auto-fix + check

npm run fix

Auto-fix formatting/linting and run the full check

Static only

npm run check:static

Run static analysis without tests

Tests only

npm 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 npm run check 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), creating parent directories as needed. Pass files: [{ path, content }] — there is no single-path form. An existing file prompts the user to confirm the overwrite, so the call returns without writing anything until that confirmation comes back; set overwrite: true on an entry to replace it without the prompt. Set append: true on an entry to add to the end of an existing file (created if missing) instead of overwriting.

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?

Goes well beyond the destructiveHint annotation by explaining the confirmation flow: an existing file pauses the call and returns without writing until the user confirms. It also discloses parent-directory creation and append behavior, which are expected side effects an agent needs to anticipate.

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 front-load the core action and limits, then cover confirmation, overwrite, and append. Every sentence earns its place and no information is repeated unnecessarily.

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 batch file-creation tool with a destructive hint and serious side effects, coverage is strong: max batch size, required fields, parent-directory creation, single-path absence, confirmation behavior, and overwrite/append variants are all stated. Nothing an agent needs to invoke it correctly is missing.

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 each field; baseline is 3. The description adds meaningful value by clarifying array-only input, the no-single-path restriction, and the overwrite confirmation behavior, which in turn explains the effect of overwrite: false.

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 operation ('create one or more files') with explicit limits (max 100) and behavior (creates parent directories). The note that there is no single-path form sharpens the contract and distinguishes it from file-editing siblings like edit and replace_text.

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?

Gives clear guidance on how to invoke the tool: pass an array of { path, content }, use overwrite: true to bypass the confirmation prompt, and append: true to add to an existing file. It does not explicitly name sibling alternatives or state when not to use create, so it stops short of a 5.

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

TDQS

A4.7/5.0
Behavior5/5

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

Annotations already flag destructiveHint=true, but the description goes well beyond that by disclosing irreversibility, the confirmation prompt for non-empty directories, the fact that deletion is deferred until confirmation, the error behavior for non-prompting clients, and workspace root protection. 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?

The description is dense but every sentence carries essential information, and the most critical facts (permanent deletion, max 1000, irreversibility) are front-loaded. The paragraph is appropriately sized for a destructive multi-option operation.

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 no output schema, the description covers the key behavioral consequences: what gets deleted, the max batch size, irreversibility, recursive and confirmation requirements, the client-prompting failure mode, and workspace root restrictions. An agent has enough information to use the tool safely and 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?

Schema coverage is 100%, so the baseline is 3. The description adds value beyond the schema by explaining that there is no single-path form, that non-empty directories require recursive=true and trigger a confirmation flow, and that workspace root directories cannot be deleted. This enriches the semantics of both paths and recursive.

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 uses a specific verb ('Permanently delete') and names the exact resources ('files, directories, or symlinks'), plus a clear cap of 1000 per call. It also distinguishes itself from a hypothetical single-path form, leaving no ambiguity about what this tool does.

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 guidance: paths must be passed as an array, there is no single-path form, non-empty directories require recursive=true, and workspace roots cannot be deleted. It does not explicitly name sibling alternatives like move or rename as the right choice for non-deletion operations, but deletion intent is unambiguous.

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.2/5.0
Behavior4/5

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

Annotations already mark the tool as read-only and closed-world. The description adds useful behavioral detail by specifying the output form ('unified diff with line counts'). It does not contradict the annotations, and it offers enough beyond them for a safe read operation.

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 concise sentences cover purpose, output format, parameter mapping, and usage context with no filler. The core action 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.

Completeness4/5

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

For a simple diff tool with read-only annotations, the description covers what it does, what it returns, and when to use it. There is no output schema, so the mention of unified diff and line counts provides the necessary return-value context. Minor gaps like failure behavior or path restrictions are not critical here.

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 parameters are already well documented. The description adds the instruction 'Pass the two paths as a and b,' which is a mild reinforcement but not substantial new meaning beyond 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 opens with a specific verb and resource: 'Compare two files and return a unified diff with line counts.' This clearly differentiates it from sibling read/list/stat tools, which inspect single paths rather than compare two files. The purpose is immediately recognizable.

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 states explicit usage contexts: 'Use after an edit dry-run to compare against another file, or to inspect changes between two paths.' It does not name alternatives or exclusions, but the guidance is clear enough for an agent to decide when to invoke this tool.

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 and only once; include 3-5 lines of surrounding context, or the edit fails listing the lines it matched. 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

TDQS

A4.6/5.0
Behavior4/5

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

Annotations already signal destructive/write behavior, and the description reinforces this by stating edits are applied and that dryRun can preview without writing. It adds useful behavioral details beyond annotations: exact-once matching, failure with matched line numbers, and the 5-file cap. It does not contradict annotations, though it could mention atomicity or partial-apply behavior on multi-edit 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?

The description is dense but every sentence earns its place: core behavior, modes, matching constraints, dry-run option, and the alternative tool. It is front-loaded with the most important operational fact and avoids unnecessary 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 destructive 5-parameter tool with no output schema, the description covers the critical invocation aspects: files cap, mode shapes, matching failure behavior, dryRun, and the main alternative. It does not describe the success return format or behavior across multiple files when one edit fails, which would make it fully complete.

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 baseline is 3. The description adds value beyond the schema by explaining the oldText uniqueness requirement, recommending 3-5 lines of context, and clarifying the two invocation modes. It does not cover ignoreWhitespace, but the schema already documents that parameter.

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 names a specific action ('apply sequential literal string replacements'), identifies the resource ('one or more files'), and scopes it with a clear limit (max 5 files per call). It also distinguishes itself from the sibling replace_text, 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 explicitly routes alternative usage: 'For glob-based bulk regex replacement across many files, use replace_text instead.' It also explains when to use dryRun and lays out the single-file vs per-file modes, giving the agent clear selection criteria.

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.6/5.0
Behavior4/5

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

Annotations already mark the operation as read-only and non-open-world, and the description adds useful behavioral context beyond that: pagination cursors reference a query-bound snapshot that expires after 60 seconds. This is valuable operational detail an agent would not otherwise know, though it does not describe output formatting 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?

Three sentences with no filler: the core function is front-loaded, followed by a key pagination caveat and sibling routing. 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?

The description covers the tool's purpose, output shape at a high level, pagination behavior, and when to use alternatives. However, 'optional metadata' is vague and there is no output schema to clarify what the response contains, so a small completeness gap remains.

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 schema carries most parameter documentation. The description adds meaningful context by explaining the pagination cursor's snapshot semantics and expiration, which directly affects how the cursor parameter should be used. It also reinforces that pattern is a glob.

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 precise verb and resource: 'Find files matching a glob pattern' and explicitly says it returns matched paths with optional metadata. It also names sibling tools it is not (search_text for content, replace_text for replacements), making it easily distinguishable.

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 explicit routing guidance: use find_files for path/glob-based file discovery, use search_text for content search, and use replace_text with the same glob for bulk replacements. This clearly tells an agent when to choose this tool over its most relevant siblings.

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

listListA
Read-only

List sorted directory entries and an ASCII tree. maxDepth=1 is top-level. maxEntries sets page size; continue with nextCursor. An incomplete first page also carries resourceUri for the whole list.

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; an incomplete first page also carries resourceUri for the whole list.
includeHiddenNoInclude hidden items (starting with .)
includeIgnoredNoInclude ignored items (node_modules, .git, etc).

TDQS

A4.1/5.0
Behavior4/5

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

Annotations already declare readOnlyHint=true, so the agent knows this is a safe read operation. The description adds valuable behavioral context: pagination via nextCursor, snapshot expiration (~60s), and the resourceUri on incomplete first pages. It also explains maxDepth semantics. This goes beyond the annotations and helps the agent understand the tool's behavior.

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 compact and front-loaded with the core purpose. The first sentence states what the tool does, and the following sentences add key behavioral details. It's efficient, though the pagination details could be slightly more structured. No wasted words.

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 read-only listing tool with 100% schema coverage and no output schema, the description covers the essential behavior: pagination, snapshot expiration, and depth semantics. It doesn't describe the exact output format of the ASCII tree, but the description says 'ASCII tree' and the tool is a list operation, so an agent can infer the return. The snapshot expiration and resourceUri details are valuable context that make it complete enough.

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 all 6 parameters. The description adds some value by explaining pagination behavior (nextCursor, resourceUri) and maxDepth semantics, but most parameter meaning 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 verb and resource: 'List sorted directory entries and an ASCII tree.' It also clarifies the tool's scope (directory listing) and distinguishes it from siblings like read, find_files, and search_text. The mention of maxDepth=1 as top-level and pagination behavior makes the purpose concrete.

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 when to use this tool: to list directory entries and an ASCII tree. It doesn't explicitly name alternatives or exclusions, but the sibling list and the description's focus on directory listing imply when it's appropriate. It could be improved by explicitly saying 'use read for file contents, find_files for searching' but the context is clear.

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.5/5.0
Behavior4/5

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

Annotations already declare readOnlyHint=trueabb, so the description adds value by explaining the scoping relationship among tools and how allowed directories are configured. It does not describe return format, but the zero-parameter nature makes the behavior straightforward.

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 no filler. The core purpose is front-loaded, followed by usage guidance and configuration sources, all concisely.

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 zero-parameter, read-only discovery tool, the description fully covers what the agent needs: what the tool lists, why to call it first, how access is configured, and that all sibling file tools are scoped to these roots.

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?

There are no parameters, so the schema needs no additional explanation. The description adds useful context about how directory access is configured, more than the schema alone would provide.

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 action ('List') and resource ('allowed workspace root directories'), and immediately establishes its unique role as the entry point for path discovery. The distinction from the sibling 'list' tool is clear through the explicit workspace-root scope.

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?

Explicitly instructs the agent to call this tool first and explains the context: all other tools are scoped to these roots. It does not name a specific alternative or when-not-to-use case, but for a discovery tool this guidance is clear and sufficient.

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.5/5.0
Behavior5/5

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

Annotations indicate destructiveHint=true and readOnlyHint=false, so the description goes beyond by disclosing critical behaviors: overwrite confirmation prompts, the lack of a bypass for move operations, self-move skipping, and the effect of copy=true with overwrite=true. This adds significant context 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 concise and front-loaded with the core purpose, then efficiently covers key behaviors in a single paragraph. There is no fluff; every sentence contributes essential information, and the structure flows logically from purpose to usage 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?

Given the tool's complexity (array of operations, max 100, overwrite logic, copy mode), the description covers all necessary aspects for correct invocation: format, limits, parent directory handling, confirmation behavior, and edge cases like self-moves. No output schema exists, so return values are not required. The description is complete.

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%, with each parameter described. The description adds value by explaining the interaction between copy and overwrite, the array-only format, and the absence of a single-pair form, which the schema does not convey. This goes beyond mere repetition and clarifies parameter semantics.

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 the tool moves, renames, or copies files and directories to explicit paths. It distinguishes from siblings by focusing on move/copy operations, while siblings like create, delete, and edit have different purposes. The mention of 'max 100 operations' and the array format adds specificity.

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

Usage Guidelines3/5

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

The description provides detailed usage instructions, such as the mandatory array format, parent directory auto-creation, and copy vs. move behavior. However, it does not explicitly state when to choose this tool over alternatives (e.g., delete vs. move, create vs. copy), leaving the agent to infer the appropriate context from the tool name and 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.9/5.0
Behavior5/5

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

Annotations declare destructiveHint=true, and the description reinforces that it writes the result. It discloses rejection behaviors (multi-file, context mismatch) and the dryRun preview option, which are not covered by annotations. 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 with no filler. The first sentence front-loads the core action and inputs, the second gives usage guidance, and the third lists constraints and the dryRun option. 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?

For a destructive file-patch tool, the description covers what it does, when to use it, its limitations, and the dryRun option. With annotations providing the destructive hint and no output schema, nothing essential is missing for an agent 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?

Schema coverage is 100% and describes each parameter. The description adds context to the diff parameter by clarifying it should come from a diff tool dry-run and that it rejects multi-file diffs and context mismatches, which goes beyond the schema's basic description. It also briefly mentions dryRun 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 states a specific verb (apply), a precise resource (a single-file unified diff to one file), and the result (write the result). It clearly differentiates from siblings like edit or replace_text by specifying the diff input and the rejection of multi-file diffs, making it distinct.

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 to use after a diff tool dry-run and to pass the diff blob directly rather than re-expressing it as line edits, which contrasts with edit/replace_text. It also states rejection conditions (multi-file diffs, mismatched context), effectively saying when not to use it.

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

TDQS

A4.6/5.0
Behavior4/5

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

Annotations already declare readOnlyHint=true, so the agent knows this is a safe read operation. The description adds key behavioral constraints: mutual exclusivity of line parameters, shared line params across batch files, and a limit of 1000 paths. It also implies content is returned but does not detail format, which is a minor gap.

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 compact, front-loads the core function, and clearly bundles related partial-read modes. It uses bullet-like lists and short sentences, with no fluff. Each clause serves a purpose, making it easy to scan.

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?

Given the tool's moderate complexity (7 params, partial reads, batch mode) and no output schema, the description covers the essential operation modes and constraints. It explains when to use batch, mutual exclusivity, and limits like max 1000 paths (though max limits are in schema, not description). It doesn't detail return format, but that is a minor gap given the read nature.

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 all parameters are documented, but the description adds crucial semantics about mutual exclusivity and batch behavior not fully captured in the schema. It clarifies how head, tail, and startLine/endLine are alternatives and how paths[] works with line params, going beyond the schema's static descriptions.

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 the tool reads one or more text files and returns content. It explicitly covers partial reads (head, tail, startLine/endLine) and batch mode via paths[]. This distinguishes it from siblings like find_files or search_text, which are for locating/searching rather than reading content.

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 explicitly states that head, tail, and startLine/endLine are mutually exclusive and instructs to use exactly one. It also clearly explains batch mode when to pass paths[] instead of path. This provides explicit when-to-use guidance and exclusion of alternatives.

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).

TDQS

A4.6/5.0
Behavior4/5

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

Annotations already flag destructiveHint=true and readOnlyHint=false. The description adds key behaviors: 'Replaces ALL occurrences per file', literal-by-default matching, and RE2 regex support. However, the wording 'Set returnDiff=true to preview changes... before or after writing' is slightly ambiguous because `returnDiff` alone does not prevent writing; `dryRun` is the true preview-without-write parameter, so this could mislead an agent.

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 tightly focused sentences, front-loaded with the tool's core purpose and key distinction from `edit`. Every sentence earns its place; there is no filler or redundant restating of the schema.

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?

The description covers the most critical context for a destructive bulk operation: it replaces all occurrences, can be scoped by glob, and can return a diff. Given a rich 100%-coverage schema and the destructiveHint annotation, it is nearly complete. The only gap is the ambiguous `returnDiff`/`dryRun` preview guidance.

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 adds value by explaining `isRegex` and `replacement` semantics: 'Literal matching by default; set isRegex=true to enable RE2 regex with capture groups ($1, $2).' This synthesizes parameter behavior beyond the schema's individual descriptions.

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?

Description states a specific verb and resource: 'Bulk search-and-replace across files matching a glob pattern.' It clearly distinguishes itself from a sibling: 'unlike edit, which replaces only the first match.' An agent can immediately tell this tool replaces all occurrences.

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 contrasts with the `edit` tool ('unlike edit, which replaces only the first match'), telling the agent when this tool is the right choice. It also advises using `returnDiff=true` to preview changes, giving practical guidance on how to use it safely.

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. Set context=N to also return N lines either side of each match (grep -C). 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.
contextNoLines of context to return either side of each match, like grep -C (default: 0, max: 10)
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.3/5.0
Behavior4/5

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

The annotations already declare readOnlyHint=true, and the description adds meaningful behavior beyond that: it specifies return shape ('matching lines with file path, 1-indexed line number and 0-indexed column offset') and context behavior. It does not mention pagination or snapshot expiration, but the cursor parameter schema covers those details, so the description is reasonably transparent.

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 front-loaded with the core purpose and output format, then gives targeted usage examples. Each sentence serves a purpose, though a few points about context and hidden files slightly echo the schema. It remains appropriately sized for an 11-parameter tool.

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 no output schemaanding many parameters, the description covers the key invocation details: what is searched, what the output looks like, how to get context, how to restrict by file type, and which sibling to use instead. Remaining details like pagination and matching rules live in the schema, which is fully described.

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 all 11 parameters. The description repeats a few useful parameter semantics, such as context=N returning N lines and pattern scoping with '**/*.ts', but it does not add meaning beyond what the schema already provides. A baseline of 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 by text or regex (grep-style).' It clearly distinguishes the tool from find_files by stating 'Use find_files to search by filename instead.' This makes the tool's scope unmistakable.

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 explicitly names the closest sibling alternative and the condition that routes to it: 'Use find_files to search by filename instead.' It also gives concrete usage direction for context, file-type scoping, and hidden-file inclusion, making when-to-use unambiguous.

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 agent knows this is a safe read operation. The description adds value by disclosing that the tool returns tokenEstimate, which is a behavioral detail beyond the schema, and by explaining that it can operate in batch mode on up to 1000 paths. It doesn't describe error behavior or permission requirements, but for a read-only metadata tool with readOnlyHint=true, the description covers the key behavioral aspects.

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 waste. The core purpose and return fields are front-loaded, the usage guidance is concise, and the two invocation modes are stated in a compact, scannable format. 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 read-only metadata tool with 100% schema coverage and readOnlyHint=true, the description is nearly complete. It covers what the tool returns, when to use it, and how to invoke it in both modes. The only minor gap is that it doesn't describe the output structure or error behavior, but since there's no output schema and the tool is simple, this is a small omission rather than a critical one.

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 both parameters (path and paths) including their mutual exclusivity and constraints. The description adds the semantic context that path is for single-file mode and paths is for batch mode, which is helpful but largely mirrors what the schema already states. Baseline 3 is appropriate 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?

The description states a specific verb ('Get metadata') and resource ('one or more files or directories'), and enumerates the exact metadata fields returned: size, type, permissions, MIME type, timestamps, and tokenEstimate. This clearly distinguishes it from sibling tools like read, list, and find_files, which have different purposes.

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 explicitly tells the agent when to use this tool: 'Use tokenEstimate to pre-screen read cost before calling read.' This is a clear usage directive that positions stat as a precursor to read. It also explains the two invocation modes (single path vs batch paths), which is practical guidance for choosing how to call it.

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

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 13 tool updatesv2.4.1
    • Changedcreate1 field changed
      • addedInput schema / $schema
        Added value: +"https://json-schema.org/draft/2020-12/schema"
    • Changeddelete1 field changed
      • addedInput schema / $schema
        Added value: +"https://json-schema.org/draft/2020-12/schema"
    • Changeddiff1 field changed
      • addedInput schema / $schema
        Added value: +"https://json-schema.org/draft/2020-12/schema"
    • Changededit3 fields changed
      • addedInput schema / $defs / EditSpec / properties / newText / examples
        Added value: +[
        +  "const x = 2;",
        +  "function newName(",
        +  ""
        +]
      • addedInput schema / $defs / EditSpec / properties / oldText / examples
        Added value: +[
        +  "const x = 1;",
        +  "function oldName("
        +]
      • addedInput schema / $schema
        Added value: +"https://json-schema.org/draft/2020-12/schema"
    • Changedfind_files2 fields changed
      • addedInput schema / $schema
        Added value: +"https://json-schema.org/draft/2020-12/schema"
      • addedInput schema / properties / pattern / examples
        Added value: +[
        +  "**/*.ts",
        +  "src/**/*.js",
        +  "*.{ts,tsx}"
        +]
    • Changedlist1 field changed
      • addedInput schema / $schema
        Added value: +"https://json-schema.org/draft/2020-12/schema"
    • Changedlist_roots1 field changed
      • addedInput schema / $schema
        Added value: +"https://json-schema.org/draft/2020-12/schema"
    • Changedmove1 field changed
      • addedInput schema / $schema
        Added value: +"https://json-schema.org/draft/2020-12/schema"
    • Changedpatch1 field changed
      • addedInput schema / $schema
        Added value: +"https://json-schema.org/draft/2020-12/schema"
    • Changedread1 field changed
      • addedInput schema / $schema
        Added value: +"https://json-schema.org/draft/2020-12/schema"
    • Changedreplace_text4 fields changed
      • addedInput schema / $schema
        Added value: +"https://json-schema.org/draft/2020-12/schema"
      • addedInput schema / properties / pattern / examples
        Added value: +[
        +  "**/*.ts",
        +  "src/**/*.js",
        +  "*.{ts,tsx}"
        +]
      • addedInput schema / properties / replacement / examples
        Added value: +[
        +  "$1_renamed",
        +  "",
        +  "TODO: fix"
        +]
      • addedInput schema / properties / searchPattern / examples
        Added value: +[
        +  "TODO",
        +  "function\\s+(\\w+)",
        +  "import.*from"
        +]
    • Changedsearch_text3 fields changed
      • addedInput schema / $schema
        Added value: +"https://json-schema.org/draft/2020-12/schema"
      • addedInput schema / properties / pattern / examples
        Added value: +[
        +  "**/*.ts",
        +  "src/**/*.js",
        +  "*.{ts,tsx}"
        +]
      • addedInput schema / properties / searchPattern / examples
        Added value: +[
        +  "TODO",
        +  "function\\s+(\\w+)",
        +  "import.*from"
        +]
    • Changedstat1 field changed
      • addedInput schema / $schema
        Added value: +"https://json-schema.org/draft/2020-12/schema"
  2. 3 tool updatesv2.3.0
    • Changedcreate2 fields changed
      • addedInput schema / properties / files / items / properties / append
        Added value: +{
        +  "description": "Append the content to the end of the file instead of overwriting; creates the file if it does not exist",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / files / items / properties / overwrite
        Added value: +{
        +  "description": "Replace an existing file without asking the user; without it an existing file prompts for confirmation",
        +  "type": "boolean"
        +}
    • Changededit1 field changed
      • changedInput schema / $defs / EditSpec / properties / oldText / description
        Previous value: -"Exact literal text to locate in the file. Must include 3-5 lines of context to ensure uniqueness and avoid matching the wrong block."New value: +"Exact literal text to locate in the file; it must match exactly once. Include 3-5 lines of context so it does — an oldText found in several places fails with their line numbers."
    • Changedsearch_text1 field changed
      • addedInput schema / properties / context
        Added value: +{
        +  "default": 0,
        +  "description": "Lines of context to return either side of each match, like grep -C (default: 0, max: 10)",
        +  "maximum": 10,
        +  "minimum": 0,
        +  "type": "integer"
        +}
  3. 5 tool updatesv2.1.5
    • Changeddelete1 field changed
      • changedOutput schema / (root)
        Previous value: -{
        -  "additionalProperties": false,
        -  "properties": {
        -    "results": {
        -      "description": "Per-path results ordered to match the input paths",
        -      "items": {
        -        "additionalProperties": false,
        -        "properties": {
        -          "error": {
        -            "additionalProperties": false,
        -            "description": "Error details; present on failure",
        -            "properties": {
        -              "code": {
        -                "type": "string"
        -              },
        -              "message": {
        -                "type": "string"
        -              },
        -              "path": {
        -                "type": "string"
        -              },
        -              "suggestion": {
        -                "type": "string"
        -              }
        -            },
        -            "required": [
        -              "code",
        -              "message"
        -            ],
        -            "type": "object"
        -          },
        -          "path": {
        -            "description": "Requested path",
        -            "type": "string"
        -          },
        -          "value": {
        -            "additionalProperties": false,
        -            "description": "Delete outcome; present on success",
        -            "properties": {
        -              "deleted": {
        -                "description": "True when the path was removed; false when the user chose Skip",
        -                "type": "boolean"
        -              }
        -            },
        -            "required": [
        -              "deleted"
        -            ],
        -            "type": "object"
        -          }
        -        },
        -        "required": [
        -          "path"
        -        ],
        -        "type": "object"
        -      },
        -      "type": "array"
        -    },
        -    "summary": {
        -      "additionalProperties": false,
        -      "properties": {
        -        "failed": {
        -          "minimum": 0,
        -          "type": "integer"
        -        },
        -        "succeeded": {
        -          "minimum": 0,
        -          "type": "integer"
        -        },
        -        "total": {
        -          "minimum": 0,
        -          "type": "integer"
        -        }
        -      },
        -      "required": [
        -        "total",
        -        "succeeded",
        -        "failed"
        -      ],
        -      "type": "object"
        -    }
        -  },
        -  "required": [
        -    "results",
        -    "summary"
        -  ],
        -  "type": "object"
        -}New value: +null
    • Changededit1 field changed
      • changedOutput schema / (root)
        Previous value: -{
        -  "additionalProperties": false,
        -  "properties": {
        -    "results": {
        -      "description": "Per-path edit results ordered to match the input paths",
        -      "items": {
        -        "additionalProperties": false,
        -        "properties": {
        -          "error": {
        -            "additionalProperties": false,
        -            "description": "Error details; present on failure",
        -            "properties": {
        -              "code": {
        -                "type": "string"
        -              },
        -              "message": {
        -                "type": "string"
        -              },
        -              "path": {
        -                "type": "string"
        -              },
        -              "suggestion": {
        -                "type": "string"
        -              }
        -            },
        -            "required": [
        -              "code",
        -              "message"
        -            ],
        -            "type": "object"
        -          },
        -          "path": {
        -            "description": "Requested file path",
        -            "type": "string"
        -          },
        -          "value": {
        -            "additionalProperties": false,
        -            "description": "Edit result; present on success",
        -            "properties": {
        -              "appliedEdits": {
        -                "description": "Number of edits successfully applied",
        -                "minimum": 0,
        -                "type": "integer"
        -              },
        -              "diff": {
        -                "description": "Unified diff of all changes (present only in dryRun mode)",
        -                "type": "string"
        -              },
        -              "kind": {
        -                "description": "Broad file kind: text, binary, image, audio, or pdf",
        -                "enum": [
        -                  "text",
        -                  "binary",
        -                  "image",
        -                  "audio",
        -                  "pdf"
        -                ],
        -                "type": "string"
        -              },
        -              "lineCount": {
        -                "description": "Number of lines in the file after edits",
        -                "minimum": 0,
        -                "type": "integer"
        -              },
        -              "lineRange": {
        -                "description": "Line range [firstLine, lastLine] covering all applied edits",
        -                "prefixItems": [
        -                  {
        -                    "exclusiveMinimum": 0,
        -                    "type": "integer"
        -                  },
        -                  {
        -                    "exclusiveMinimum": 0,
        -                    "type": "integer"
        -                  }
        -                ],
        -                "type": "array"
        -              },
        -              "linesAdded": {
        -                "description": "Net lines added by all applied edits",
        -                "minimum": 0,
        -                "type": "integer"
        -              },
        -              "linesRemoved": {
        -                "description": "Net lines removed by all applied edits",
        -                "minimum": 0,
        -                "type": "integer"
        -              },
        -              "mimeType": {
        -                "description": "Detected MIME type of the file",
        -                "type": "string"
        -              },
        -              "modified": {
        -                "description": "Last modification timestamp after edits (ISO 8601 UTC)",
        -                "format": "date-time",
        -                "type": "string"
        -              },
        -              "path": {
        -                "description": "Resolved absolute path of the edited file",
        -                "type": "string"
        -              },
        -              "resourceUri": {
        -                "description": "Resource URI pointing to the updated file content; omitted when no edit matched (appliedEdits is 0) and the file was left untouched",
        -                "type": "string"
        -              },
        -              "size": {
        -                "description": "File size in bytes after edits",
        -                "minimum": 0,
        -                "type": "integer"
        -              },
        -              "unmatchedEdits": {
        -                "description": "oldText values that did not match any content in the file",
        -                "items": {
        -                  "type": "string"
        -                },
        -                "type": "array"
        -              }
        -            },
        -            "required": [
        -              "path",
        -              "size",
        -              "lineCount",
        -              "mimeType",
        -              "kind",
        -              "modified",
        -              "appliedEdits"
        -            ],
        -            "type": "object"
        -          }
        -        },
        -        "required": [
        -          "path"
        -        ],
        -        "type": "object"
        -      },
        -      "type": "array"
        -    },
        -    "summary": {
        -      "additionalProperties": false,
        -      "properties": {
        -        "failed": {
        -          "minimum": 0,
        -          "type": "integer"
        -        },
        -        "succeeded": {
        -          "minimum": 0,
        -          "type": "integer"
        -        },
        -        "total": {
        -          "minimum": 0,
        -          "type": "integer"
        -        }
        -      },
        -      "required": [
        -        "total",
        -        "succeeded",
        -        "failed"
        -      ],
        -      "type": "object"
        -    }
        -  },
        -  "required": [
        -    "results",
        -    "summary"
        -  ],
        -  "type": "object"
        -}New value: +null
    • Changedlist1 field changed
      • changedInput schema / properties / maxEntries / description
        Previous value: -"Page size (default: 1000). Continue with nextCursor; resourceUri is only for hard-cap overflow."New value: +"Page size (default: 1000). Continue with nextCursor; an incomplete first page also carries resourceUri for the whole list."
    • Changedread1 field changed
      • changedOutput schema / (root)
        Previous value: -{
        -  "additionalProperties": false,
        -  "properties": {
        -    "results": {
        -      "description": "Per-path results ordered to match the input paths",
        -      "items": {
        -        "additionalProperties": false,
        -        "properties": {
        -          "error": {
        -            "additionalProperties": false,
        -            "description": "Error details; present on failure",
        -            "properties": {
        -              "code": {
        -                "type": "string"
        -              },
        -              "message": {
        -                "type": "string"
        -              },
        -              "path": {
        -                "type": "string"
        -              },
        -              "suggestion": {
        -                "type": "string"
        -              }
        -            },
        -            "required": [
        -              "code",
        -              "message"
        -            ],
        -            "type": "object"
        -          },
        -          "path": {
        -            "description": "Requested file path",
        -            "type": "string"
        -          },
        -          "value": {
        -            "additionalProperties": false,
        -            "description": "Read result; present on success",
        -            "properties": {
        -              "contentHash": {
        -                "description": "SHA-256 hex digest of the returned content (present when includeHash=true)",
        -                "pattern": "^[0-9a-f]{64}$",
        -                "type": "string"
        -              },
        -              "continuation": {
        -                "additionalProperties": false,
        -                "description": "Next-read arguments; present when content was truncated due to size limits",
        -                "properties": {
        -                  "args": {
        -                    "additionalProperties": false,
        -                    "description": "Ready-to-use arguments for the next call; pass verbatim",
        -                    "properties": {
        -                      "endLine": {
        -                        "exclusiveMinimum": 0,
        -                        "type": "integer"
        -                      },
        -                      "path": {
        -                        "type": "string"
        -                      },
        -                      "startLine": {
        -                        "exclusiveMinimum": 0,
        -                        "type": "integer"
        -                      }
        -                    },
        -                    "required": [
        -                      "path",
        -                      "startLine",
        -                      "endLine"
        -                    ],
        -                    "type": "object"
        -                  },
        -                  "hint": {
        -                    "description": "One-sentence description of the data still remaining to be read",
        -                    "type": "string"
        -                  },
        -                  "tool": {
        -                    "description": "Tool name to call for the next chunk",
        -                    "type": "string"
        -                  }
        -                },
        -                "required": [
        -                  "tool",
        -                  "args",
        -                  "hint"
        -                ],
        -                "type": "object"
        -              },
        -              "endLine": {
        -                "description": "End line",
        -                "exclusiveMinimum": 0,
        -                "type": "integer"
        -              },
        -              "hasMoreLines": {
        -                "description": "True when additional lines remain beyond what was returned",
        -                "type": "boolean"
        -              },
        -              "head": {
        -                "description": "Head lines requested",
        -                "exclusiveMinimum": 0,
        -                "type": "integer"
        -              },
        -              "kind": {
        -                "description": "Broad file kind: text, binary, image, audio, or pdf",
        -                "enum": [
        -                  "text",
        -                  "binary",
        -                  "image",
        -                  "audio",
        -                  "pdf"
        -                ],
        -                "type": "string"
        -              },
        -              "linesRead": {
        -                "description": "Number of lines returned in this response",
        -                "minimum": 0,
        -                "type": "integer"
        -              },
        -              "mimeType": {
        -                "description": "Detected MIME type (e.g. text/typescript)",
        -                "type": "string"
        -              },
        -              "resourceUri": {
        -                "description": "Resource URI for externalized content (present when file is stored in resource store)",
        -                "type": "string"
        -              },
        -              "startLine": {
        -                "description": "Start line",
        -                "exclusiveMinimum": 0,
        -                "type": "integer"
        -              },
        -              "tail": {
        -                "description": "Tail lines requested",
        -                "exclusiveMinimum": 0,
        -                "type": "integer"
        -              },
        -              "totalLines": {
        -                "description": "Total line count in the full file",
        -                "minimum": 0,
        -                "type": "integer"
        -              }
        -            },
        -            "type": "object"
        -          }
        -        },
        -        "required": [
        -          "path"
        -        ],
        -        "type": "object"
        -      },
        -      "type": "array"
        -    },
        -    "summary": {
        -      "additionalProperties": false,
        -      "properties": {
        -        "failed": {
        -          "minimum": 0,
        -          "type": "integer"
        -        },
        -        "succeeded": {
        -          "minimum": 0,
        -          "type": "integer"
        -        },
        -        "total": {
        -          "minimum": 0,
        -          "type": "integer"
        -        }
        -      },
        -      "required": [
        -        "total",
        -        "succeeded",
        -        "failed"
        -      ],
        -      "type": "object"
        -    }
        -  },
        -  "required": [
        -    "results",
        -    "summary"
        -  ],
        -  "type": "object"
        -}New value: +null
    • Changedreplace_text1 field changed
      • changedOutput schema / (root)
        Previous value: -{
        -  "additionalProperties": false,
        -  "properties": {
        -    "diff": {
        -      "description": "Unified diff of all changes (present when returnDiff=true or dryRun=true)",
        -      "type": "string"
        -    },
        -    "diffTruncated": {
        -      "description": "True when the diff was cut due to the size limit",
        -      "type": "boolean"
        -    },
        -    "filesScanned": {
        -      "description": "Total number of files examined",
        -      "minimum": 0,
        -      "type": "integer"
        -    },
        -    "results": {
        -      "description": "Per-file results: modified files, then any that could not be processed",
        -      "items": {
        -        "additionalProperties": false,
        -        "properties": {
        -          "error": {
        -            "additionalProperties": false,
        -            "description": "Error details; present on failure",
        -            "properties": {
        -              "code": {
        -                "type": "string"
        -              },
        -              "message": {
        -                "type": "string"
        -              },
        -              "path": {
        -                "type": "string"
        -              },
        -              "suggestion": {
        -                "type": "string"
        -              }
        -            },
        -            "required": [
        -              "code",
        -              "message"
        -            ],
        -            "type": "object"
        -          },
        -          "path": {
        -            "description": "File path relative to the search root",
        -            "type": "string"
        -          },
        -          "value": {
        -            "additionalProperties": false,
        -            "description": "Replacement outcome; present on success",
        -            "properties": {
        -              "matches": {
        -                "description": "Replacements applied in this file",
        -                "minimum": 0,
        -                "type": "integer"
        -              }
        -            },
        -            "required": [
        -              "matches"
        -            ],
        -            "type": "object"
        -          }
        -        },
        -        "required": [
        -          "path"
        -        ],
        -        "type": "object"
        -      },
        -      "type": "array"
        -    },
        -    "resultsTruncated": {
        -      "description": "True when the results list holds fewer entries than summary.total: the changed-file or failed-file cap was hit. Trust summary over results.length.",
        -      "type": "boolean"
        -    },
        -    "stoppedReason": {
        -      "description": "Why 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.",
        -      "enum": [
        -        "maxResults",
        -        "maxFiles",
        -        "timeout"
        -      ],
        -      "type": "string"
        -    },
        -    "summary": {
        -      "additionalProperties": false,
        -      "properties": {
        -        "failed": {
        -          "minimum": 0,
        -          "type": "integer"
        -        },
        -        "succeeded": {
        -          "minimum": 0,
        -          "type": "integer"
        -        },
        -        "total": {
        -          "minimum": 0,
        -          "type": "integer"
        -        }
        -      },
        -      "required": [
        -        "total",
        -        "succeeded",
        -        "failed"
        -      ],
        -      "type": "object"
        -    },
        -    "totalMatches": {
        -      "description": "Total number of replacements made across all files",
        -      "minimum": 0,
        -      "type": "integer"
        -    }
        -  },
        -  "required": [
        -    "results",
        -    "summary",
        -    "totalMatches",
        -    "filesScanned"
        -  ],
        -  "type": "object"
        -}New value: +null
  4. 28 tool updatesv2.0.0
    • Removedapply_patch
    • Removedcalculate_hash
    • Addedcreate
    • Addeddelete
    • Addeddiff
    • Removeddiff_files
    • Changededit27 fields changed
      • addedInput schema / $defs
        Added value: +{
        +  "EditSpec": {
        +    "additionalProperties": false,
        +    "properties": {
        +      "newText": {
        +        "description": "Replacement text. Use an empty string to delete the matched oldText.",
        +        "type": "string"
        +      },
        +      "oldText": {
        +        "description": "Exact literal text to locate in the file. Must include 3-5 lines of context to ensure uniqueness and avoid matching the wrong block.",
        +        "minLength": 1,
        +        "type": "string"
        +      }
        +    },
        +    "required": [
        +      "oldText",
        +      "newText"
        +    ],
        +    "type": "object"
        +  }
        +}
      • removedInput schema / $schema
        Removed value: -"https://json-schema.org/draft/2020-12/schema"
      • addedInput schema / oneOf
        Added value: +[
        +  {
        +    "required": [
        +      "path",
        +      "edits"
        +    ]
        +  },
        +  {
        +    "required": [
        +      "files"
        +    ]
        +  }
        +]
      • changedInput schema / properties / dryRun / description
        Previous value: -"Preview edits without writing. Check `unmatchedEdits` in response."New value: +"Preview diffs without writing to disk (default: false = apply edits)"
      • changedInput schema / properties / edits / description
        Previous value: -"List of replacements to apply sequentially. Each edit replaces the first occurrence of oldText."New value: +"Replacements applied to path; not allowed when using files"
      • addedInput schema / properties / edits / items / $ref
        Added value: +"#/$defs/EditSpec"
      • removedInput schema / properties / edits / items / additionalProperties
        Removed value: -false
      • removedInput schema / properties / edits / items / properties
        Removed value: -{
        -  "newText": {
        -    "description": "Replacement string. Preserve surrounding indentation style.",
        -    "type": "string"
        -  },
        -  "oldText": {
        -    "description": "Exact literal string to replace (character-for-character). Include 3–5 lines of context for unique targeting.",
        -    "maxLength": 102400,
        -    "minLength": 1,
        -    "type": "string"
        -  }
        -}
      • removedInput schema / properties / edits / items / required
        Removed value: -[
        -  "oldText",
        -  "newText"
        -]
      • removedInput schema / properties / edits / items / type
        Removed value: -"object"
      • addedInput schema / properties / edits / maxItems
        Added value: +100
      • addedInput schema / properties / files
        Added value: +{
        +  "description": "Per-file entries (batch mode)",
        +  "items": {
        +    "additionalProperties": false,
        +    "properties": {
        +      "edits": {
        +        "description": "Replacements to apply to this specific file",
        +        "items": {
        +          "$ref": "#/$defs/EditSpec"
        +        },
        +        "maxItems": 100,
        +        "minItems": 1,
        +        "type": "array"
        +      },
        +      "path": {
        +        "description": "File or directory path inside an allowed workspace root.",
        +        "maxLength": 4096,
        +        "minLength": 1,
        +        "type": "string"
        +      }
        +    },
        +    "required": [
        +      "path",
        +      "edits"
        +    ],
        +    "type": "object"
        +  },
        +  "maxItems": 5,
        +  "minItems": 1,
        +  "type": "array"
        +}
      • changedInput schema / properties / ignoreWhitespace / description
        Previous value: -"Treat all whitespace sequences as equivalent when matching oldText."New value: +"Ignore leading/trailing whitespace differences when matching oldText"
      • changedInput schema / properties / path / description
        Previous value: -"Absolute path to file or directory."New value: +"Single file path; mutually exclusive with files"
      • removedInput schema / required
        Removed value: -[
        -  "path",
        -  "edits"
        -]
      • removedOutput schema / $schema
        Removed value: -"https://json-schema.org/draft/2020-12/schema"
      • removedOutput schema / properties / appliedEdits
        Removed value: -{
        -  "maximum": 9007199254740991,
        -  "minimum": 0,
        -  "type": "integer"
        -}
      • removedOutput schema / properties / diff
        Removed value: -{
        -  "description": "Unified diff of changes (dryRun)",
        -  "type": "string"
        -}
      • removedOutput schema / properties / lineRange
        Removed value: -{
        -  "description": "Line range modified [start, end] (1-based)",
        -  "prefixItems": [
        -    {
        -      "maximum": 9007199254740991,
        -      "minimum": 1,
        -      "type": "integer"
        -    },
        -    {
        -      "maximum": 9007199254740991,
        -      "minimum": 1,
        -      "type": "integer"
        -    }
        -  ],
        -  "type": "array"
        -}
      • removedOutput schema / properties / linesAdded
        Removed value: -{
        -  "description": "Lines added",
        -  "maximum": 9007199254740991,
        -  "minimum": 0,
        -  "type": "integer"
        -}
      • removedOutput schema / properties / linesRemoved
        Removed value: -{
        -  "description": "Lines removed",
        -  "maximum": 9007199254740991,
        -  "minimum": 0,
        -  "type": "integer"
        -}
      • removedOutput schema / properties / ok
        Removed value: -{
        -  "type": "boolean"
        -}
      • removedOutput schema / properties / path
        Removed value: -{
        -  "type": "string"
        -}
      • addedOutput schema / properties / results
        Added value: +{
        +  "description": "Per-path edit results ordered to match the input paths",
        +  "items": {
        +    "additionalProperties": false,
        +    "properties": {
        +      "error": {
        +        "additionalProperties": false,
        +        "description": "Error details; present on failure",
        +        "properties": {
        +          "code": {
        +            "type": "string"
        +          },
        +          "message": {
        +            "type": "string"
        +          },
        +          "path": {
        +            "type": "string"
        +          },
        +          "suggestion": {
        +            "type": "string"
        +          }
        +        },
        +        "required": [
        +          "code",
        +          "message"
        +        ],
        +        "type": "object"
        +      },
        +      "path": {
        +        "description": "Requested file path",
        +        "type": "string"
        +      },
        +      "value": {
        +        "additionalProperties": false,
        +        "description": "Edit result; present on success",
        +        "properties": {
        +          "appliedEdits": {
        +            "description": "Number of edits successfully applied",
        +            "minimum": 0,
        +            "type": "integer"
        +          },
        +          "diff": {
        +            "description": "Unified diff of all changes (present only in dryRun mode)",
        +            "type": "string"
        +          },
        +          "kind": {
        +            "description": "Broad file kind: text, binary, image, audio, or pdf",
        +            "enum": [
        +              "text",
        +              "binary",
        +              "image",
        +              "audio",
        +              "pdf"
        +            ],
        +            "type": "string"
        +          },
        +          "lineCount": {
        +            "description": "Number of lines in the file after edits",
        +            "minimum": 0,
        +            "type": "integer"
        +          },
        +          "lineRange": {
        +            "description": "Line range [firstLine, lastLine] covering all applied edits",
        +            "prefixItems": [
        +              {
        +                "exclusiveMinimum": 0,
        +                "type": "integer"
        +              },
        +              {
        +                "exclusiveMinimum": 0,
        +                "type": "integer"
        +              }
        +            ],
        +            "type": "array"
        +          },
        +          "linesAdded": {
        +            "description": "Net lines added by all applied edits",
        +            "minimum": 0,
        +            "type": "integer"
        +          },
        +          "linesRemoved": {
        +            "description": "Net lines removed by all applied edits",
        +            "minimum": 0,
        +            "type": "integer"
        +          },
        +          "mimeType": {
        +            "description": "Detected MIME type of the file",
        +            "type": "string"
        +          },
        +          "modified": {
        +            "description": "Last modification timestamp after edits (ISO 8601 UTC)",
        +            "format": "date-time",
        +            "type": "string"
        +          },
        +          "path": {
        +            "description": "Resolved absolute path of the edited file",
        +            "type": "string"
        +          },
        +          "resourceUri": {
        +            "description": "Resource URI pointing to the updated file content; omitted when no edit matched (appliedEdits is 0) and the file was left untouched",
        +            "type": "string"
        +          },
        +          "size": {
        +            "description": "File size in bytes after edits",
        +            "minimum": 0,
        +            "type": "integer"
        +          },
        +          "unmatchedEdits": {
        +            "description": "oldText values that did not match any content in the file",
        +            "items": {
        +              "type": "string"
        +            },
        +            "type": "array"
        +          }
        +        },
        +        "required": [
        +          "path",
        +          "size",
        +          "lineCount",
        +          "mimeType",
        +          "kind",
        +          "modified",
        +          "appliedEdits"
        +        ],
        +        "type": "object"
        +      }
        +    },
        +    "required": [
        +      "path"
        +    ],
        +    "type": "object"
        +  },
        +  "type": "array"
        +}
      • addedOutput schema / properties / summary
        Added value: +{
        +  "additionalProperties": false,
        +  "properties": {
        +    "failed": {
        +      "minimum": 0,
        +      "type": "integer"
        +    },
        +    "succeeded": {
        +      "minimum": 0,
        +      "type": "integer"
        +    },
        +    "total": {
        +      "minimum": 0,
        +      "type": "integer"
        +    }
        +  },
        +  "required": [
        +    "total",
        +    "succeeded",
        +    "failed"
        +  ],
        +  "type": "object"
        +}
      • removedOutput schema / properties / unmatchedEdits
        Removed value: -{
        -  "description": "Edits that could not be applied",
        -  "items": {
        -    "type": "string"
        -  },
        -  "type": "array"
        -}
      • changedOutput schema / required
        Previous value: -[
        -  "ok"
        -]New value: +[
        +  "results",
        +  "summary"
        +]
    • Removedfind
    • Addedfind_files
    • Removedgrep
    • Addedlist
    • Addedlist_roots
    • Removedls
    • Removedmkdir
    • Addedmove
    • Removedmv
    • Addedpatch
    • Changedread31 fields changed
      • removedInput schema / $schema
        Removed value: -"https://json-schema.org/draft/2020-12/schema"
      • addedInput schema / dependentRequired
        Added value: +{
        +  "endLine": [
        +    "startLine"
        +  ]
        +}
      • removedInput schema / description
        Removed value: -"Use one read mode only: 'head', 'tail', or 'startLine'/'endLine'."
      • addedInput schema / oneOf
        Added value: +[
        +  {
        +    "required": [
        +      "path"
        +    ]
        +  },
        +  {
        +    "required": [
        +      "paths"
        +    ]
        +  }
        +]
      • changedInput schema / properties / endLine / description
        Previous value: -"End line (1-based, inclusive). Defaults to last line when startLine is set."New value: +"End line (1-indexed)"
      • changedInput schema / properties / endLine / maximum
        Previous value: -9007199254740991New value: +100000
      • changedInput schema / properties / head / description
        Previous value: -"Read first N lines (preview)"New value: +"Return first N lines"
      • changedInput schema / properties / includeHash / description
        Previous value: -"Include SHA-256 hash of full file content"New value: +"Include SHA-256 hash of the returned content in the response"
      • changedInput schema / properties / path / description
        Previous value: -"Absolute path to file or directory."New value: +"Single file path; mutually exclusive with paths"
      • addedInput schema / properties / paths
        Added value: +{
        +  "description": "Array of file paths for batch mode (max 1000); mutually exclusive with path",
        +  "items": {
        +    "description": "File or directory path inside an allowed workspace root.",
        +    "maxLength": 4096,
        +    "minLength": 1,
        +    "type": "string"
        +  },
        +  "maxItems": 1000,
        +  "minItems": 1,
        +  "type": "array"
        +}
      • changedInput schema / properties / startLine / description
        Previous value: -"Start line (1-based, inclusive). Defaults to 1 when endLine is set."New value: +"Start line (1-indexed)"
      • changedInput schema / properties / startLine / maximum
        Previous value: -9007199254740991New value: +100000
      • changedInput schema / properties / tail / description
        Previous value: -"Read last N lines"New value: +"Return last N lines"
      • removedInput schema / required
        Removed value: -[
        -  "path"
        -]
      • removedOutput schema / $schema
        Removed value: -"https://json-schema.org/draft/2020-12/schema"
      • removedOutput schema / properties / content
        Removed value: -{
        -  "description": "Content",
        -  "type": "string"
        -}
      • removedOutput schema / properties / contentHash
        Removed value: -{
        -  "description": "SHA-256 of full file content",
        -  "pattern": "^[a-f0-9]{64}$",
        -  "type": "string"
        -}
      • removedOutput schema / properties / endLine
        Removed value: -{
        -  "description": "End line",
        -  "maximum": 9007199254740991,
        -  "minimum": 1,
        -  "type": "integer"
        -}
      • removedOutput schema / properties / hasMoreLines
        Removed value: -{
        -  "description": "More lines?",
        -  "type": "boolean"
        -}
      • removedOutput schema / properties / head
        Removed value: -{
        -  "description": "Head lines",
        -  "maximum": 9007199254740991,
        -  "minimum": 1,
        -  "type": "integer"
        -}
      • removedOutput schema / properties / linesRead
        Removed value: -{
        -  "description": "Lines read",
        -  "maximum": 9007199254740991,
        -  "minimum": 0,
        -  "type": "integer"
        -}
      • removedOutput schema / properties / ok
        Removed value: -{
        -  "const": true,
        -  "type": "boolean"
        -}
      • removedOutput schema / properties / path
        Removed value: -{
        -  "type": "string"
        -}
      • removedOutput schema / properties / resourceUri
        Removed value: -{
        -  "description": "Full content URI",
        -  "type": "string"
        -}
      • addedOutput schema / properties / results
        Added value: +{
        +  "description": "Per-path results ordered to match the input paths",
        +  "items": {
        +    "additionalProperties": false,
        +    "properties": {
        +      "error": {
        +        "additionalProperties": false,
        +        "description": "Error details; present on failure",
        +        "properties": {
        +          "code": {
        +            "type": "string"
        +          },
        +          "message": {
        +            "type": "string"
        +          },
        +          "path": {
        +            "type": "string"
        +          },
        +          "suggestion": {
        +            "type": "string"
        +          }
        +        },
        +        "required": [
        +          "code",
        +          "message"
        +        ],
        +        "type": "object"
        +      },
        +      "path": {
        +        "description": "Requested file path",
        +        "type": "string"
        +      },
        +      "value": {
        +        "additionalProperties": false,
        +        "description": "Read result; present on success",
        +        "properties": {
        +          "contentHash": {
        +            "description": "SHA-256 hex digest of the returned content (present when includeHash=true)",
        +            "pattern": "^[0-9a-f]{64}$",
        +            "type": "string"
        +          },
        +          "continuation": {
        +            "additionalProperties": false,
        +            "description": "Next-read arguments; present when content was truncated due to size limits",
        +            "properties": {
        +              "args": {
        +                "additionalProperties": false,
        +                "description": "Ready-to-use arguments for the next call; pass verbatim",
        +                "properties": {
        +                  "endLine": {
        +                    "exclusiveMinimum": 0,
        +                    "type": "integer"
        +                  },
        +                  "path": {
        +                    "type": "string"
        +                  },
        +                  "startLine": {
        +                    "exclusiveMinimum": 0,
        +                    "type": "integer"
        +                  }
        +                },
        +                "required": [
        +                  "path",
        +                  "startLine",
        +                  "endLine"
        +                ],
        +                "type": "object"
        +              },
        +              "hint": {
        +                "description": "One-sentence description of the data still remaining to be read",
        +                "type": "string"
        +              },
        +              "tool": {
        +                "description": "Tool name to call for the next chunk",
        +                "type": "string"
        +              }
        +            },
        +            "required": [
        +              "tool",
        +              "args",
        +              "hint"
        +            ],
        +            "type": "object"
        +          },
        +          "endLine": {
        +            "description": "End line",
        +            "exclusiveMinimum": 0,
        +            "type": "integer"
        +          },
        +          "hasMoreLines": {
        +            "description": "True when additional lines remain beyond what was returned",
        +            "type": "boolean"
        +          },
        +          "head": {
        +            "description": "Head lines requested",
        +            "exclusiveMinimum": 0,
        +            "type": "integer"
        +          },
        +          "kind": {
        +            "description": "Broad file kind: text, binary, image, audio, or pdf",
        +            "enum": [
        +              "text",
        +              "binary",
        +              "image",
        +              "audio",
        +              "pdf"
        +            ],
        +            "type": "string"
        +          },
        +          "linesRead": {
        +            "description": "Number of lines returned in this response",
        +            "minimum": 0,
        +            "type": "integer"
        +          },
        +          "mimeType": {
        +            "description": "Detected MIME type (e.g. text/typescript)",
        +            "type": "string"
        +          },
        +          "resourceUri": {
        +            "description": "Resource URI for externalized content (present when file is stored in resource store)",
        +            "type": "string"
        +          },
        +          "startLine": {
        +            "description": "Start line",
        +            "exclusiveMinimum": 0,
        +            "type": "integer"
        +          },
        +          "tail": {
        +            "description": "Tail lines requested",
        +            "exclusiveMinimum": 0,
        +            "type": "integer"
        +          },
        +          "totalLines": {
        +            "description": "Total line count in the full file",
        +            "minimum": 0,
        +            "type": "integer"
        +          }
        +        },
        +        "type": "object"
        +      }
        +    },
        +    "required": [
        +      "path"
        +    ],
        +    "type": "object"
        +  },
        +  "type": "array"
        +}
      • removedOutput schema / properties / startLine
        Removed value: -{
        -  "description": "Start line",
        -  "maximum": 9007199254740991,
        -  "minimum": 1,
        -  "type": "integer"
        -}
      • addedOutput schema / properties / summary
        Added value: +{
        +  "additionalProperties": false,
        +  "properties": {
        +    "failed": {
        +      "minimum": 0,
        +      "type": "integer"
        +    },
        +    "succeeded": {
        +      "minimum": 0,
        +      "type": "integer"
        +    },
        +    "total": {
        +      "minimum": 0,
        +      "type": "integer"
        +    }
        +  },
        +  "required": [
        +    "total",
        +    "succeeded",
        +    "failed"
        +  ],
        +  "type": "object"
        +}
      • removedOutput schema / properties / tail
        Removed value: -{
        -  "description": "Tail lines",
        -  "maximum": 9007199254740991,
        -  "minimum": 1,
        -  "type": "integer"
        -}
      • removedOutput schema / properties / totalLines
        Removed value: -{
        -  "description": "Total lines",
        -  "maximum": 9007199254740991,
        -  "minimum": 0,
        -  "type": "integer"
        -}
      • removedOutput schema / properties / truncated
        Removed value: -{
        -  "description": "Truncated?",
        -  "type": "boolean"
        -}
      • changedOutput schema / required
        Previous value: -[
        -  "ok"
        -]New value: +[
        +  "results",
        +  "summary"
        +]
    • Removedread_many
    • Addedreplace_text
    • Removedrm
    • Removedroots
    • Removedsearch_and_replace
    • Addedsearch_text
    • Changedstat6 fields changed
      • removedInput schema / $schema
        Removed value: -"https://json-schema.org/draft/2020-12/schema"
      • addedInput schema / oneOf
        Added value: +[
        +  {
        +    "required": [
        +      "path"
        +    ]
        +  },
        +  {
        +    "required": [
        +      "paths"
        +    ]
        +  }
        +]
      • changedInput schema / properties / path / description
        Previous value: -"Absolute path to file or directory."New value: +"Single file path; mutually exclusive with paths"
      • addedInput schema / properties / paths
        Added value: +{
        +  "description": "Array of file paths for batch mode (max 1000); mutually exclusive with path",
        +  "items": {
        +    "description": "File or directory path inside an allowed workspace root.",
        +    "maxLength": 4096,
        +    "minLength": 1,
        +    "type": "string"
        +  },
        +  "maxItems": 1000,
        +  "minItems": 1,
        +  "type": "array"
        +}
      • removedInput schema / required
        Removed value: -[
        -  "path"
        -]
      • changedOutput schema / (root)
        Previous value: -{
        -  "$schema": "https://json-schema.org/draft/2020-12/schema",
        -  "additionalProperties": false,
        -  "properties": {
        -    "info": {
        -      "additionalProperties": false,
        -      "properties": {
        -        "accessed": {
        -          "description": "Accessed",
        -          "format": "date-time",
        -          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$",
        -          "type": "string"
        -        },
        -        "created": {
        -          "description": "Created",
        -          "format": "date-time",
        -          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$",
        -          "type": "string"
        -        },
        -        "isHidden": {
        -          "description": "Hidden?",
        -          "type": "boolean"
        -        },
        -        "mimeType": {
        -          "description": "MIME type",
        -          "type": "string"
        -        },
        -        "modified": {
        -          "description": "Modified",
        -          "format": "date-time",
        -          "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$",
        -          "type": "string"
        -        },
        -        "name": {
        -          "description": "Name",
        -          "type": "string"
        -        },
        -        "path": {
        -          "description": "Absolute path",
        -          "type": "string"
        -        },
        -        "permissions": {
        -          "description": "Permissions",
        -          "type": "string"
        -        },
        -        "size": {
        -          "description": "Size (bytes)",
        -          "maximum": 9007199254740991,
        -          "minimum": 0,
        -          "type": "integer"
        -        },
        -        "symlinkTarget": {
        -          "description": "Target (symlink)",
        -          "type": "string"
        -        },
        -        "tokenEstimate": {
        -          "description": "Est. tokens (size/4)",
        -          "maximum": 9007199254740991,
        -          "minimum": 0,
        -          "type": "integer"
        -        },
        -        "type": {
        -          "description": "Type",
        -          "enum": [
        -            "file",
        -            "directory",
        -            "symlink",
        -            "other"
        -          ],
        -          "type": "string"
        -        }
        -      },
        -      "required": [
        -        "name",
        -        "path",
        -        "type",
        -        "size",
        -        "created",
        -        "modified",
        -        "accessed",
        -        "permissions",
        -        "isHidden"
        -      ],
        -      "type": "object"
        -    },
        -    "ok": {
        -      "const": true,
        -      "type": "boolean"
        -    }
        -  },
        -  "required": [
        -    "ok"
        -  ],
        -  "type": "object"
        -}New value: +null
    • Removedstat_many
    • Removedtree
    • Removedwrite

TDQS

A4.4/5.0

Scored across 13 tools

Disambiguation5/5

Each tool targets a distinct file system operation — listing, reading, writing, editing, moving, diffing, searching, etc. Even overlapping operations like edit vs replace_text are clearly differentiated by scope (literal sequential vs bulk regex) and search_text vs find_files by content vs filename. No ambiguity remains.

Naming Consistency4/5

Most tools follow a clear verb or verb_noun pattern (create, delete, read, list_roots, search_text). The only deviation is the mix of single-word verbs (list, diff, stat) and compound verbs (replace_text, find_files), but all use snake_case consistently, making the set predictable.

Tool Count5/5

13 tools is well-scoped for a filesystem server. Each tool has a distinct purpose and none feel redundant. The count covers the breadth of file operations without excessive granularity or missing essentials.

Completeness5/5

The tool surface covers the full file lifecycle: create, read, edit, patch, move (with copy), delete, plus metadata (stat), listing (list/find), search, and root discovery. Operations are logically paired (e.g., diff and patch enable safe application of changes), and bulk variants exist for efficiency. No obvious gaps that would break agent workflows.

Maintenance

ActivityActive
ResponsivenessSlow

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
    D
    maintenance
    Experimental MCP server for local LLM orchestration with filesystem tools (read, write, list, delete files) and a CLI agent that communicates via Ollama.
    5 npm
    ISC