Skip to main content
Glama
patchloom

Patchloom

Official

Patchloom

CI Security crates.io Release License

Tests Coverage OpenSSF Best Practices OpenSSF Scorecard FOSSA Status

Docs VS Code Marketplace crates.io downloads

One binary. Every platform. Structured file edits for AI agents.

Patchloom is a single-binary CLI that gives AI coding agents safe, structured file editing on any operating system. It edits JSON, YAML, and TOML by selector (not regex), preserves comments, understands code structure across 20 languages, batches multiple file edits into one tool call, and works identically on Linux, macOS, and Windows.

Not a generic filesystem MCP. Default MCP filesystem servers read/write files as text. Patchloom adds dry-run previews, parser-backed config and markdown edits, AST ops, multi-file batch/tx with undo, and stable error_kind peels for hosts. Full coding agents (Claude Code, Codex, Cursor) own the loop; Patchloom is the tool layer they (or a Rust embedder) call.

Patchloom demo: 6 edits across 4 files in JSON, YAML, and TOML: one command, comments preserved

# Edit a YAML value by selector without breaking comments or formatting
patchloom doc set config.yaml database.port 5432 --apply

# Batch 6 file edits into a single tool call
patchloom batch --apply <<'EOF'
doc.set package.json version "2.0.0"
doc.set config.yaml app.version "2.0.0"
doc.set config.toml project.version "2.0.0"
replace README.md "1.0.0" "2.0.0"
replace CHANGELOG.md "1.0.0" "2.0.0"
file.create VERSION "2.0.0"
EOF

Why Patchloom? | Install | Quick start | Commands | Comparison | When to use what | Architecture | Status


Why Patchloom?

The problem

AI agents edit files through tool calls. Each call is a round-trip back to the LLM. When a task touches config files, that process has three failure modes:

  1. Syntax corruption. The agent uses text replacement on JSON, YAML, or TOML and produces invalid output (mismatched braces, broken indentation, lost comments).

  2. Round-trip tax. Editing 6 files means 6 separate tool calls. Each one waits for the LLM to generate, execute, read the result, and plan the next call.

  3. Platform fragmentation. On Linux the agent uses sed, jq, grep. On Windows, none of those exist. The agent falls back to verbose PowerShell or makes errors with unfamiliar syntax.

How patchloom solves each one

Problem

How patchloom solves it

Syntax corruption

doc commands parse the file, change the value by selector path, and write valid output. Comments and formatting are preserved. No regex needed.

Round-trip tax

batch and tx combine N operations into 1 tool call. Six file edits become one command with atomic rollback on failure.

Platform fragmentation

Single static binary with zero dependencies. Same commands, same flags, same behavior on Linux, macOS, and Windows.

What changes with patchloom

Without patchloom (6 tool calls)

Agent: edit file 1  ─── tool call ───▶  15s
Agent: edit file 2  ─── tool call ───▶  15s
Agent: edit file 3  ─── tool call ───▶  15s
Agent: edit file 4  ─── tool call ───▶  15s
Agent: edit file 5  ─── tool call ───▶  15s
Agent: edit file 6  ─── tool call ───▶  15s
                                    Total: ~90s

With patchloom batch (1 tool call)

Agent: batch with
  all 6 edits     ─── tool call ───▶  25s



                  5 round-trips saved
                                    Total: ~25s

Key capabilities

Capability

What it does

Example

Parser-backed edits

Edit JSON/YAML/TOML by selector, preserving comments and formatting

doc set config.yaml db.port 5432 --apply

Batch N files in 1 call

batch and tx combine operations into one tool call with rollback

batch --apply < ops.txt

Comment preservation

YAML/TOML comments survive all edits, including array resizing

doc append config.yaml tags '"v2"' --apply

Heading-aware markdown

Edit sections, tables, and bullets by heading, not line number

md table-append README.md --heading "API" --row "| new | row |" --apply

AST-aware code ops

List, rename, replace, and analyze symbols across 20 languages

ast rename src/ --old old_name --new new_name --apply

Atomic rollback

strict: true reverts every file if format or validate steps fail

tx plan.json --apply

MCP server

Expose all operations as structured MCP tool calls

patchloom mcp-server

Optional CLI sandbox

Reject ../ / absolute path escapes from --cwd on reads and writes (off by default; MCP always on)

patchloom --cwd <ws> --contain search … / create … --apply

Cross-platform

Identical behavior on Linux, macOS, Windows. No sed, jq, grep required.

Same binary everywhere

When to use patchloom vs native tools

Patchloom is not a replacement for all file operations. Its instructions tell agents exactly when to use it and when native tools are faster:

Task

Use patchloom?

Why

Edit a JSON/YAML/TOML value by selector

Yes

Parser guarantees valid output, preserves comments

Edit 3+ files in one task

Yes

batch/tx eliminates round-trips

Append a row to a markdown table

Yes

Heading-aware, no line number guessing

Read a single file

No

Native read_file is faster

Simple text search

No

Native grep is faster

Single-file text replacement

No

Native search_replace is faster

Correctness over speed

Patchloom is not faster than native tools for simple, single-file edits. Use native tools for those. But native text replacement cannot safely edit structured files: a sed on YAML can corrupt indentation, strip comments, or produce invalid syntax. doc set parses the file, changes the value by selector, and writes valid output. That guarantee is the point.

Where patchloom is faster is multi-file batching. Six file edits via native tools means six round-trips to the LLM. One batch call does the same work in a single round-trip.

Task                    PL-CLI    MCP    Native
──────────────────────  ──────  ──────  ──────
search                   18.5s   12.7s   13.9s  ◀ ~same
replace                  36.1s   26.6s   26.1s  ◀ ~same
doc_set                  30.9s   16.9s   13.7s  ◀ native fastest
md_table                 15.5s   13.5s   15.3s  ◀ MCP fastest
tx_multi_file            41.4s   28.5s   22.9s  ◀ native fastest
batch_6_files            50.6s   46.6s   30.3s  ◀ native fastest
batch_mixed_ops          24.7s   13.6s   20.9s  ◀ MCP fastest
yaml_comment_preserve    18.1s   11.6s   16.1s  ◀ MCP fastest
md_insert                15.0s   11.7s   15.7s  ◀ MCP fastest
file_ops                 26.0s   16.6s   17.2s  ◀ ~same
tidy                     45.0s   30.3s   41.7s  ◀ MCP fastest
──────────────────────  ──────  ──────  ──────
TOTAL                   321.9s  228.5s  233.8s

MCP mode wins overall (228.5s vs 233.8s native) because structured tool calls skip shell syntax construction entirely. MCP wins 5/11 tasks; native wins 3/11; 3 are ties. CLI mode is always slowest due to shell construction overhead.


Related MCP server: ast-editor

Install

Prefer channels that track each GitHub Release (Homebrew, Scoop, crates, npm, Releases). On Windows, Scoop is recommended. winget (Patchloom.Patchloom) is published per release and is usually current after Microsoft's publish pipeline (winget source update if search is stale). Chocolatey often lags while community moderation runs.

# Homebrew (macOS/Linux)
brew install patchloom/tap/patchloom

# crates.io (requires Rust 1.95+, includes MCP server)
cargo install patchloom

# npm / npx (downloads the platform binary from GitHub Releases)
npx patchloom --version
# or: npm install -g patchloom
# Scoop (Windows; recommended Windows channel)
scoop bucket add patchloom https://github.com/patchloom/scoop-bucket
scoop install patchloom/patchloom

Pre-built binaries for Linux, macOS, and Windows are on the Releases page. See Installation for shell installer scripts, source builds, shell completions, and winget / Chocolatey notes.

  • MCP Registry name: mcp-name: io.github.patchloom/patchloom

Editor extension

Install the companion extension for VS Code, Cursor, Windsurf, or VSCodium:

The extension auto-discovers the CLI (or installs it for you), generates AGENTS.md, configures MCP servers, and adds Quick Actions to the command palette. See the Editor Extension guide for details.

Quick start

1. Set up your project

patchloom init

This creates AGENTS.md in a new project or appends the rules to an existing agent instructions file, offers shell completions, and detects MCP configuration opportunities. Pass -y to skip confirmation prompts.

If you only want the rules text:

patchloom agent-rules >> AGENTS.md

# Or tailor the output:
patchloom agent-rules --mode mcp >> AGENTS.md            # MCP-only (no CLI examples)
patchloom agent-rules --platform windows >> AGENTS.md    # Windows-only syntax

If .vscode/ or .cursor/ exists, init also prints ready-to-copy .vscode/mcp.json or .cursor/mcp.json snippets.

Your AI agent reads AGENTS.md and learns when to use patchloom vs native tools.

2. Edit a config file safely

# Parser-backed: changes the value, preserves comments and formatting
patchloom doc set config.yaml database.port 5432 --apply

3. Batch multiple edits into one call

patchloom batch --apply <<'EOF'
doc.set config.json version '"2.0.0"'
md.upsert_bullet AGENTS.md "Rules" "- Always test"
replace src/main.rs "v1" "v2"
EOF

Values are JSON-first: unquoted 2.0 becomes a number. Force a string with nested quotes as above (Unix shells).

On Windows PowerShell (no bash heredoc), write ops to a file:

@'
doc.set config.json version "\"2.0.0\""
md.upsert_bullet AGENTS.md "Rules" "- Always test"
replace src/main.rs "v1" "v2"
'@ | Set-Content ops.txt -Encoding utf8
patchloom batch --apply ops.txt

Or use a JSON plan with format and validate lifecycle:

{
  "version": 1,
  "operations": [
    { "op": "doc.set", "path": "config.json", "selector": "version", "value": "2.0.0" },
    { "op": "md.upsert_bullet", "path": "AGENTS.md", "heading": "Rules", "bullet": "- Always test" },
    { "op": "replace", "path": "src/main.rs", "old": "v1", "new": "v2" }
  ],
  "format": [{ "cmd": "cargo fmt --all" }],
  "validate": [{ "cmd": "cargo test", "required": true }]
}
patchloom tx plan.json --apply

tx plans are trusted input. format and validate run their cmd fields through the host shell (sh -c on Unix, cmd /C on Windows), so only run plans you trust.

4. Or use MCP for structured tool calls (no shell syntax)

After installing with MCP support, start the server:

PATCHLOOM_MCP_SURFACE=core patchloom mcp-server

MCP-capable agents call patchloom tools directly as structured JSON, with no shell quoting or command construction. The agent sends {"path": "config.json", "selector": "version", "value": "2.0"} instead of building patchloom doc set config.json version '"2.0"' --apply.

Coding agents: set PATCHLOOM_MCP_SURFACE=core for a 12-tool pack (list_files, search/read/replace, doc/md, execute_plan, operation_schema, server_info) so schemas stay small. Product default remains full inventory when the env is unset. Prefer Patchloom MCP alone for list+edit (no second filesystem MCP). See the MCP setup guide for Cursor / Claude / Codex paste configs and the full security model.

Using VS Code, Cursor, or Windsurf? The Patchloom extension handles setup automatically: it installs the binary, runs init, and configures your editor's MCP settings.

As a Rust library

Host teams embedding Patchloom instead of a private edit stack: see the embedder host case study (for_agent, peels, fuzzy refuse, apply_fragment, path-only ops).

Add patchloom as a dependency (omit CLI/MCP/AST with default-features = false):

[dependencies]
patchloom = { version = "0.37.6", default-features = false } <!-- x-release-please-version -->
use patchloom::api::{self, ApplyMode, ReplaceOptions, edit_error_kind, EditErrorKind};
use std::path::Path;

// Replace text (preview only, no disk write)
let result = api::replace_text(
    Path::new("src/config.rs"),
    "old_value", "new_value",
    &ReplaceOptions::default(),
    ApplyMode::Preview,
    None,
)?;
println!("{}", result.diff);

// Agent hosts: shared primary+fallback policy (unique, require_change, fuzzy @ 0.90)
let opts = ReplaceOptions::for_agent();
// Fail closed: zero matches become EditErrorKind::NoMatch
match api::replace_in_content("body", "missing", "x", &opts) {
    Ok(r) => println!("changed={}", r.changed),
    Err(e) => assert_eq!(edit_error_kind(&e), Some(EditErrorKind::NoMatch)),
}
// for_agent auto-refuses over-wide fuzzy; custom options use api::fuzzy_span_suspicious
// Buffer multi-op + host write: api::refuse_batch_if_suspicious_fuzzy after apply_content_edits
// Invalid options and bad regex peel InvalidInput (CLI/tx typed errors included)
match api::replace_in_content("body", "", "x", &ReplaceOptions::default()) {
    Err(e) => assert_eq!(edit_error_kind(&e), Some(EditErrorKind::InvalidInput)),
    Ok(_) => panic!("empty pattern must error"),
}

// Set a value in a JSON file
api::doc_set(
    Path::new("config.json"),
    "version",
    serde_json::json!("2.0"),
    ApplyMode::Apply,
    None,
)?;

// Multi-doc YAML: merge into document 0 (selector None = root only)
api::doc_merge(
    Path::new("stream.yaml"),
    serde_json::json!({"env": "prod"}),
    ApplyMode::Apply,
    None,
    Some("0"),
)?;

// Sole-path text load: binary → EditErrorKind::Binary; invalid UTF-8 → InvalidEncoding
let _text = api::load_text(Path::new("notes.md"))?;

All API types are Send + Sync. Beyond the api module, utility modules are also public: containment (workspace path guarding), exec (shell command execution), files (file-walking, load_text_strict, binary detection), backup (restore_path_from_latest_backup for post-Apply validate/revert), and write (atomic file writes with policy transformations). Library users needing temp dirs (e.g. agents) can use PathGuard::builder(cwd).allow_temp_directory() (handles /tmp on macOS); see the containment and api module rustdocs. Multi-doc bare keys and wrong-root merges peel to EditErrorKind::TypeError via edit_error_kind. Create/rename dest-exists peels to EditErrorKind::AlreadyExists (or api::is_already_exists / api::error_kind_str for CLI-stable "already_exists" strings). Fine-grained kinds also have bool peels (is_not_found, is_conflicts, is_changes_detected, is_type_error, is_format_failed, is_guard_rejected, is_invalid_input, is_no_match, is_ambiguous) matching edit_error_kind.

Replace fail-closed / shell-token options: CLI replace --require-change and --command-position (also plan/MCP fields and ReplaceOptions on the library). Agent hosts: ReplaceOptions::for_agent() on primary and fallback replace paths (auto span refuse); custom options still call api::fuzzy_span_suspicious / FuzzySpanPolicy after fuzzy Apply; buffer multi-op hosts call api::refuse_batch_if_suspicious_fuzzy after apply_content_edits (#2064). Library-only AST mutators: ast_rename / ast_replace_in_symbol / ast_rename_batch (feature ast + files), and FunctionSigEdit::parse_rust. Ordered host onboarding: Embedder host checklist (#2009). Full surface: docs.rs/patchloom.

Getting started

Resource

What you'll learn

Installation

Install options and shell completions

Core concepts

Write modes, transaction plans, exit codes

MCP setup

Configure patchloom as an MCP server for your agent

Editor extension

VS Code, Cursor, Windsurf, and VSCodium integration

Quickstart

5-minute walkthrough

Reference

Every command, operation, and mode

Examples

Transaction plan templates

Commands

Agent-optimized (these are faster or safer than native tools)

Command

What it does

When to use

batch

Line-oriented multi-file edits in 1 call

Editing 3+ files with simple syntax

tx

JSON plan with format/validate lifecycle

Complex multi-file edits with rollback

doc

Parser-backed JSON/YAML/TOML edits

Changing config values without breaking syntax

md

Heading-aware markdown edits

Updating tables, sections, bullets in docs

ast

AST-aware symbol operations (20 languages)

Renaming identifiers, listing symbols, impact analysis

patch

Apply unified diffs with stale detection

Replaying patches safely

tidy

Text-file whitespace and newline normalization

CI checks for text tidiness

mcp-server

MCP protocol server

MCP-capable agents (no shell syntax)

General-purpose (also useful in scripts and CI)

Command

Description

search

Fast literal or regex search across text files (supports --glob/--exclude/--ignore-file for layered custom ignore files, --max-results, -C context, etc.)

replace

Mechanical string replacement across text files with diff preview

apply-fragment

Freeform fragment with required anchors (MorphLLM-style markers stripped; no cloud merge)

append

Append content to an existing file

prepend

Prepend content to an existing file

create

Create a new file with content

delete

Delete a file

rename

Move (rename) a file

read

Read file contents with optional line range

status

Show which files have uncommitted changes

explain

Summarize a tx plan in plain English

undo

Restore files from a backup created by --apply

completions

Generate shell completions (bash, zsh, fish, elvish)

init

Set up patchloom in a project (agent rules, completions, MCP)

schema

Export operation schemas with tier filtering and system prompts

agent-rules

Generate agent instructions for your project

How patchloom compares

Tool

Strength

Where patchloom differs

jq

JSON query/transform

patchloom also handles YAML, TOML, env, ini, properties, and markdown; batches across files; preserves comments

yq

YAML/JSON query/transform

patchloom preserves YAML comments via CST editing; also edits TOML, env, ini, properties, and markdown; adds batching and atomic transactions

dasel

Multi-format get/set

patchloom doc covers JSON, YAML, TOML, env, ini, and properties. It adds batching (N edits in 1 call), atomic rollback, and a format/validate lifecycle. XML, HCL, CSV, and KDL stay with dasel or yq

sd

Regex find/replace

patchloom adds parser-backed structured edits; batching; never produces invalid JSON/YAML

comby

Structural code patterns

patchloom targets config files and agent workflows, not source code pattern matching

The key difference: patchloom is designed for AI agent workflows. One batch or tx call replaces N sequential tool calls, cutting round-trips and eliminating partial-failure states.

vs agent-native editing tools

The table above compares patchloom to human CLI tools. But agents already have built-in editing: Claude Code's edit_file, Cursor's apply, Grok Build's search_replace, Aider's /code blocks. Why add patchloom on top?

Agent-native tools use text matching. They find a block of text and replace it. This works for source code but fails on structured config files:

Agent uses search_replace on YAML

database:
  # Production settings
  host: db.prod.internal
  port: 5432  # PostgreSQL default
  pool_size: 10

The agent replaces port: 5432 with port: 5433. Result depends on implementation. Many agents lose the inline comment, break indentation, or fail to match because of surrounding context changes.

Agent uses patchloom doc set

patchloom doc set config.yaml \
  database.port 5433 --apply

The YAML parser changes the value at the selector path. Comments, indentation, key ordering, and all other formatting are preserved. The output is always valid YAML.

Limitation of agent-native tools

How patchloom addresses it

Comment destruction

CST-level YAML/TOML editing preserves all comments

One file per tool call

batch/tx edit N files in 1 call (6.7x faster in benchmarks)

No rollback

tx with strict: true reverts all files if validation fails

Platform-dependent

Same binary and syntax on Linux, macOS, Windows

Stale context risk

patch apply uses fuzz matching to handle context drift

When to keep using native tools: Single-file reads, simple text search, single-file text replacement where comments don't matter. Patchloom's agent-rules tell agents exactly when to use each approach.

When to use what

Need

Prefer

Prefer something else

JSON, YAML, TOML, env, ini, or properties by path

Patchloom doc

Generic filesystem MCP / blind text replace

Multi-doc YAML stream

Patchloom selectors (0.key)

Bare key on stream root

Structural code pattern search

ast-grep

Text-only grep for shapes

Identifier rename in code

Patchloom ast rename

Fuzzy text replace for symbols

Multi-file atomic apply + undo

Patchloom batch / tx

N sequential shell edits

Freeform snippet with known anchor (after/before/old)

Patchloom apply-fragment (strips Morph-style // ... existing code ... markers)

Whole-file rewrite or guessing placement

Freeform snippet without anchors (cloud model merge)

Morph Fast Apply or similar

Patchloom (anchor-less Morph merge is a non-goal)

Full agent product

Claude Code / Codex / Cursor

Patchloom alone

Longer write-ups: Comparisons · Embedder host checklist · MCP setup

Library hosts: Embedder host checklist: dual-path ReplaceOptions::for_agent() (primary + fallback, includes refuse_suspicious_fuzzy), peels via edit_error_kind / is_* / is_fuzzy_span_suspicious with #[non_exhaustive] _ arm, multi-op ContentEditsResult.op_honesty + refuse_batch_if_suspicious_fuzzy after buffer multi-op (#2064), plan/tx widest matched_text, optional apply_content_edits_to_file_with_span_policy. Custom options still use api::fuzzy_span_suspicious / FuzzySpanPolicy after fuzzy Apply.

Context budget: line-range read, search --count / --files-with-matches, one batch/tx, --jsonl for large streams.

How it works with your AI agent

Two integration modes, same capabilities:

flowchart LR
    subgraph CLI["CLI mode (any agent)"]
        direction TB
        A["patchloom agent-rules >> AGENTS.md"] --> B["Agent reads AGENTS.md"]
        B --> C{"What kind of edit?"}
        C -->|Simple edit| D["Native tool (faster)"]
        C -->|Config edit| E["patchloom doc (safer)"]
        C -->|Markdown edit| F["patchloom md (smarter)"]
        C -->|Multi-file edit| G["patchloom batch (batched)"]
    end

    subgraph MCP["MCP mode (MCP-capable agents)"]
        direction TB
        H["patchloom mcp-server"] --> I["Agent discovers tools via MCP"]
        I --> J["Structured JSON tool calls"]
        J --> K["No shell syntax needed"]
    end

Status

5900+ tests across 25 commands. Tested with Grok 4.3, GPT-5.4, and Claude Opus 4.6.

Component

Status

CLI

Install from crates.io, Homebrew, Scoop, npm (npx patchloom), or GitHub Releases. Also on winget (Patchloom.Patchloom; usually current after Microsoft publish) and Chocolatey (community moderation often lags GitHub).

MCP server

Official MCP Registry name io.github.patchloom/patchloom (stdio; crates.io / npm packages; see server.json). Local MCPB for Smithery / desktop hosts: make pack-mcpb (mcpb/). Glama listing (glama.json; keep description aligned with server.json, see MCP setup)

Editor extension

Published on VS Code Marketplace and Open VSX

Full command reference

Every command, flag, transaction operation, and exit code is documented in the Command Reference (also available at docs/reference/README.md).

License

Licensed under either of:

at your option.

Contributing

See CONTRIBUTING.md.

For local verification before opening a pull request, run make check. It covers the main Linux test and lint gate: formatting, clippy, unit tests (including feature-matrix jobs), integration tests, PTY tests, release-notes structure, test hygiene, generated-doc freshness (check-patchloom-md, check-readme), server-json-test, verify-homebrew-version-test, packaging-script unit tests (scoop-manifest-test, chocolatey-package-test, pack-mcpb-test, force-release-version-test), workflow-sanity-test, apply-release-notes-test, and dco-check-test. It is not every GitHub required check: audit, deny, and Windows stay in GitHub Actions. While iterating locally, make check-fast is the same except it skips only check-patchloom-md (it still runs check-readme, server-json-test, verify-homebrew-version-test, the packaging-script tests, workflow-sanity-test, apply-release-notes-test, and dco-check-test).

Pull request titles must use one Conventional Commits prefix (feat, fix, docs, style, refactor, perf, test, build, ci, chore, revert; no commas or +). See CONTRIBUTING.md.

All commits must be signed off with git commit -s.

Agent integration tests

make agent-test runs 19 pytest scenarios that verify AI agents correctly use patchloom when given instructions. make bench-agent runs 3-way benchmarks (CLI vs MCP vs native) across 11 tasks. Use MODEL=X to switch models and RUNS=N for variance reduction. Requires an LLM API key. Not part of make check. See tests/agent/README.md for details.

Security

For current security reporting guidance, see SECURITY.md.

Available Tools

66 tools
append_fileB
Destructive

Append content to an existing file. Inserts the file's line ending first when the file does not already end with one. Example: {"content":"#[test]\nfn new_test() {}\n","path":"tests/test.rs"}

NameRequiredDescriptionDefault
pathYes
contentYes
agent_presetNoWhen true, replace uses the agent preset: unique, require_change, fuzzy floor 0.90, allow_absent_old false. Off unless set.
expected_sha256NoSHA-256 hex of the file's current bytes. If it does not match, the tool returns error_kind stale and writes nothing.

TDQS

B3.2/5.0
Behavior3/5

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

Annotations already declare destructiveHint=true and readOnlyHint=false, so the mutation profile is known. The description adds genuine value by disclosing the line-ending insertion behavior, but says nothing about the stale-write protection (expected_sha256), error handling, or whether existing content is preserved — relevant for a destructive write tool.

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?

Two crisp sentences plus a concrete example. Purpose is front-loaded and the line-ending behavior follows immediately. The example earns its place by demonstrating the exact parameter shape, though it is slightly more verbose than strictly necessary.

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

Completeness3/5

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

For a destructive write tool with no output schema and a partly-documented schema, the description covers the core behavior and line-ending nuance but omits error/return semantics, the role of expected_sha256 staleness, and how it differs from create_file/prepend_file. Adequate but with clear gaps.

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?

Coverage is 50%: agent_preset and expected_sha256 are documented in the schema, while path and content carry no schema description. The description's example partially compensates by showing how path and content are used, but the ambiguity of agent_preset's interaction with append behavior is unaddressed. Baseline 3 is appropriate.

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

Purpose4/5

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

States a specific verb+resource ('Append content to an existing file') that is clearly distinguishable from siblings like prepend_file, create_file, and replace_text. It doesn't explicitly name those siblings, so routing relies on the agent inferring the difference, keeping it just below a 5.

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

Usage Guidelines2/5

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

The phrase 'to an existing file' implicitly signals this is not for creating files, but there is no explicit when-to-use guidance, no when-not-to-use, and no reference to alternatives such as prepend_file or create_file. The agent must infer the routing.

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

apply_fragmentA
Destructive

Constrained freeform fragment apply (#2018). Strips Morph-style // ... existing code ... marker lines from fragment, then inserts or replaces at a required unique anchor (exactly one of after, before, old). Fail-closed: no anchor-less Morph model merge. Prefer for lazy-snippet agent output when anchors are known; use replace/ast for precise edits. Morph-class freeform fragment with required placement (exactly one of after/before/old). Lazy // ... existing code ... lines are stripped; no model merge without anchors (#2018). Example: {"fragment":"// ... existing code ...\n bar();\n// ... existing code ...\n","path":"src/lib.rs","after":"fn foo() {"}

NameRequiredDescriptionDefault
oldNoReplace this unique span with the cleaned fragment.
pathYesFile to edit.
afterNoInsert cleaned fragment after this unique anchor.
beforeNoInsert cleaned fragment before this unique anchor.
uniqueNoFail if the anchor matches more than once (default true).
fragmentYesNew text or Morph-style snippet (lazy marker lines stripped). Aliases `new`/`to`/`content` match replace_text agent priors.
instructionNoOptional human instruction (explain only; not used for merge).
agent_presetNoWhen true, replace uses the agent preset: unique, require_change, fuzzy floor 0.90, allow_absent_old false. Off unless set.
expected_sha256NoSHA-256 hex of the file's current bytes. If it does not match, the tool returns error_kind stale and writes nothing.

TDQS

A3.6/5.0
Behavior4/5

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

Annotations already declare readOnlyHint=false and destructiveHint=true, so safety is covered; the description adds real behavior beyond that: fail-closed (no anchor-less model merge), marker-line stripping, and the requirement of exactly one anchor. It does not describe the return shape or the stale-error path beyond what the schema already carries.

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

Conciseness2/5

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

The core content is repeated almost verbatim across the paragraph ('Morph-class freeform fragment with required placement... no model merge without anchors'), so several sentences do not earn their place. The first sentence is well front-loaded, but the duplication makes the whole entry noticeably bloated.

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 9-parameter mutation tool with no output schema, the description covers the critical behaviors: anchor requirement, marker stripping, fail-closed semantics, and an example. It could say more about success/failure outcomes, but annotations plus the schema fill most remaining gaps.

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% and the schema itself already states 'Exactly one of after, before, or old must be set', so the description mostly reinforces what is documented. The inline example adds marginal value by showing fragment/path/after in use, but it does not add syntax or semantics the schema lacks.

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

Purpose4/5

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

States a concrete verb+resource ('freeform fragment apply') and scope (strips Morph-style markers, inserts/replaces at a required anchor). It names an alternative ('use replace/ast for precise edits'), so an agent can partly distinguish it from siblings. The purpose is clear but the doubled phrasing and internal ticket references (#2018) add friction rather than sharpen it.

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?

'Prefer for lazy-snippet agent output when anchors are known; use replace/ast for precise edits' gives an explicit when-to-use condition and an alternative tool. It does not state an explicit when-not to use beyond the fail-closed constraint, but the selection guidance is concrete rather than implied.

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

apply_patchA
Destructive

Apply a unified diff, a Codex *** Begin Patch document, or an Aider SEARCH/REPLACE / DiffFenced document. Default apply=true writes (same as CLI patch apply --apply). Set apply=false for check-only preview (CLI patch check; disk is unchanged). The diff parameter is the full unified diff text, a *** Begin Patch ... *** End Patch envelope (Add/Update/Delete/Move), or <<<<<<< SEARCH / ======= / >>>>>>> REPLACE blocks (dest path above ------- after SEARCH). SEARCH/REPLACE is unique by default (multi-match is ambiguous, no write); set replace_all=true to update every exact match. Empty-hunk +++ /dev/null (git deleted file mode, no hunks) unlinks. A hunked delete applies minus lines first; leftover bytes rewrite the file (preview --diff). Stale minus lines are ambiguous and the file is not removed; regenerate minus lines or use file.delete for path-only unlink. Use on_stale=merge for three-way merge on stale unified-diff context; allow_conflicts=true writes conflict markers. Never commit files containing conflict markers. Example: {"diff": "--- a/file.txt\n+++ b/file.txt\n@@ -1 +1 @@\n-old\n+new", "on_stale": "fail"}

NameRequiredDescriptionDefault
diffYes
applyNoWhen true (default), apply the patch. Set `apply=false` for check-only preview (CLI `patch check`; disk is unchanged).
strictNoRoll back all writes when format/validate lifecycle steps fail.
on_staleNofail
replace_allNoSEARCH/REPLACE only: update every exact match. Default unique.
allow_conflictsNo

TDQS

A4.2/5.0
Behavior5/5

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

Well beyond the destructiveHint=true annotation, it discloses that multi-match SEARCH/REPLACE is ambiguous and results in no write, that empty-hunk /dev/null unlinks, that stale minus lines leave the file untouched, that allow_conflicts writes conflict markers, and warns never to commit conflict-marker files. This is unusually rich behavioral disclosure for a mutation tool.

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?

Front-loads the core action and each clause carries real information, so virtually nothing is wasted. However it is delivered as a single dense run-on paragraph full of semicolons and jargon, which costs some readability for a complex 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?

Covers formats, default write behavior, edge cases (stale context, empty-hunk unlink, conflict markers), and recovery advice, which is substantial for a destructive tool with no output schema. Return values/result reporting are not described, and 'strict' is unexplained, leaving minor gaps.

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?

With only 50% schema description coverage, the description compensates by explaining the diff formats in depth, apply's default and preview semantics, replace_all's uniqueness rule, on_stale=merge, and allow_conflicts=true. Only the 'strict' parameter (rollback on lifecycle failure) is left to the schema, so it nearly closes the coverage gap.

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

Purpose4/5

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

States a precise verb ('Apply') and enumerates the resource/input forms it accepts: unified diff, Codex *** Begin Patch, and Aider SEARCH/REPLACE. This is specific and unambiguous, but it never names or contrasts with siblings such as apply_fragment, replace_text, or batch_replace, so sibling differentiation is left implicit.

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?

Provides clear in-tool routing: apply=true writes vs apply=false is check-only, on_stale=merge for three-way merges, replace_all for multi-match, and explicitly recommends file.delete for path-only unlink. There is no high-level statement of when to pick this tool over the sibling patch/replace tools, which keeps it 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.

ast_delete_symbolB
Destructive

Delete a whole symbol span, including leading doc comments and attributes, and collapse surrounding blank lines to one. Deletes the full symbol span (docs and attributes included) and collapses surrounding blank lines. Example: {"symbol":"unused_helper","path":"src/lib.rs"}

NameRequiredDescriptionDefault
langNoLanguage hint (e.g. "rust", "go"). Overrides extension-based detection.
pathYesFile containing the symbol.
symbolYesSymbol name to delete (qualified names like `Impl::method` accepted).
agent_presetNoWhen true, replace uses the agent preset: unique, require_change, fuzzy floor 0.90, allow_absent_old false. Off unless set.
expected_sha256NoSHA-256 hex of the file's current bytes. If it does not match, the tool returns error_kind stale and writes nothing.

TDQS

B3.4/5.0
Behavior4/5

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

Annotations already declare destructiveHint=true and openWorldHint=false, so the safety profile is covered; the description adds genuinely new context by specifying that the deletion swallows leading doc comments and attributes and that blank lines collapse to one. It still omits irreversibility/undo availability and what happens when the symbol is absent.

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

Conciseness3/5

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

The first and second sentences say the same thing almost verbatim ('Delete... including leading doc comments and attributes, and collapse surrounding blank lines' / 'Deletes the full symbol span (docs and attributes included) and collapses surrounding blank lines'), wasting a full sentence. The example is useful and the core action is front-loaded, but a quarter of the text is redundant.

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, no-output-schema mutation whose annotations already flag destructiveness, the description covers the action, the destruction footprint, and a usage example. Gaps are minor: absence/error behavior and whether the deletion is reversible are left unstated.

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 lang, expected_sha256, and agent_preset are already documented; the description only reinforces path and symbol via an example. That is the baseline 3 when the schema carries the load, with the example adding marginal value.

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

Purpose4/5

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

States a specific verb (delete) and precise resource (a whole symbol span), with scope qualifiers — leading doc comments, attributes, and surrounding blank-line collapsing — that functionally separate it from ast_rename and ast_replace_symbol. It never names a sibling explicitly, so it falls short of full differentiation.

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

Usage Guidelines2/5

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

No guidance on when to choose this over ast_replace_symbol, ast_rename, or delete_file, and no prerequisites stated. The example shows a bare invocation but not the conditions under which deletion is appropriate, and nothing mentions the stale/expected_sha256 workflow.

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

ast_depsB
Read-only

Extract import/dependency statements from source files. Supports Rust, Python, JS/TS, Go, Java, C/C++, Ruby, PHP. Use reverse=true to find what imports a file. Example: {"path": "src/main.rs"}

NameRequiredDescriptionDefault
langNoLanguage hint.
pathYesFile or directory to analyze (relative to working directory).
reverseNoShow reverse dependencies (what imports this file).

TDQS

B3.4/5.0
Behavior3/5

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

Annotations already declare readOnlyHint=true and openWorldHint=false, so the safety profile is covered. The description adds the supported-language list and the reverse-lookup behavior, but says nothing about output shape or performance characteristics, so it clears the (lower) annotated bar without excelling.

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?

Three tight sentences plus a minimal example, with the core purpose front-loaded and the reverse hint placed before the example. Nothing is padded, though the language list is somewhat enumerative.

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

Completeness3/5

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

For a read-only, three-parameter tool the description is largely adequate, but with no output schema it still omits any indication of the return format (flat list vs. grouped by file) and does not disambiguate from the adjacent ast_imports tool.

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

Parameters3/5

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

Schema coverage is 100%, so the schema already documents path, lang, and reverse. The description's mention of reverse=true and the path example merely restate schema content, adding no format or semantic detail beyond it. Baseline 3 applies when the schema does the heavy lifting.

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

Purpose4/5

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

States a specific verb (Extract) and resource (import/dependency statements from source files) and enumerates the supported languages, so the scope is concrete. However, it never distinguishes itself from the sibling ast_imports tool, which appears to cover overlapping ground, leaving the agent to guess which to pick.

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 explains the reverse=true mode ('find what imports a file'), which is useful conditional guidance, and supplies a call example. But there is no explicit when-to-use versus ast_imports or ast_refs, so the routing guidance is only implied.

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

ast_diffA
Read-only

Structural diff between two versions of a file. Shows added, removed, and modified symbols (not line-level diff). Compares against git refs. Example: {"path": "src/lib.rs", "from": "HEAD~1"}

NameRequiredDescriptionDefault
toNoGit ref for the "new" version (default: working tree).
fromNoGit ref for the "old" version (default: HEAD).HEAD
langNoLanguage hint.
pathYesFile to diff (relative to working directory).

TDQS

A4.2/5.0
Behavior4/5

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

Annotations already declare readOnlyHint=true and openWorldHint=false, so the description's added value is the output semantics: symbol-level (added/removed/modified) rather than line-level, and comparison against git refs. It does not disclose error behavior for non-git directories or non-source files, but that is a modest gap against a safe-read annotation profile.

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 front-loaded sentences: purpose, scope contrast, then mechanics and an example. No filler, and the most decision-relevant fact (structural, not line-level) comes second.

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?

With no output schema, the description carries the return-value burden and names the diff categories returned. It leaves unstated what happens with unsupported languages or non-versioned files, but is otherwise sufficient for a 4-parameter read tool.

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 defaults for from/to and the language hint are already documented structurally, establishing the baseline of 3. The description's example reinforces path and from usage but adds no meaning beyond what the schema provides.

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

Purpose5/5

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

States a specific verb+resource ('structural diff between two versions of a file') and immediately narrows scope by contrasting with the line-level alternative. An agent can distinguish it from ast_read or doc_diff without opening the schema.

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

Usage Guidelines4/5

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

Explains that comparison happens against git refs and provides a concrete invocation example with path and from, which effectively shows how to use it. It stops short of naming when-not-to-use conditions or pointing to a sibling for line-level diffs.

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

ast_extract_to_fileB
Destructive

Extract a symbol (module, function, struct) to a separate file. For modules with unwrap=true, content is un-indented. Example: {"source": "src/lib.rs", "symbol": "tests", "target": "src/lib_tests.rs", "replacement": "mod tests;", "prepend": "use super::*;"}

NameRequiredDescriptionDefault
langNoLanguage hint.
forceNoOverwrite target if it exists.
sourceYesSource file containing the symbol.
symbolYesName of the symbol to extract.
targetYesDestination file path.
unwrapNoIf true (default), remove wrapper and un-indent for modules.
prependNoContent to prepend to the target file.
replacementNoText to leave in place of the extracted block.
update_importsNoRewrite consumer `use`/import statements of the extracted symbol.
new_module_pathNoModule path consumers should import from (required with `update_imports`).
old_module_pathNoModule path consumers currently import from (required with `update_imports`).

TDQS

B3.2/5.0
Behavior3/5

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

Annotations already declare destructiveHint=true and readOnlyHint=false, so the agent knows this mutates files. The description adds that modules with unwrap=true get un-indented content, which is useful behavioral context. However, it doesn't explain what gets destroyed (e.g., the source file's original block is replaced by 'replacement' text), the overwrite semantics (covered by the 'force' parameter schema), or the required preconditions for update_imports beyond what the schema already says.

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 two sentences and an example: the first states the purpose, the second highlights a specific behavioral detail (unwrap), and the example shows parameter usage. It's front-loaded and free of waste, though the example could be seen as slightly verbose.

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

Completeness3/5

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

For a destructive tool with 11 parameters, no output schema, and 100% schema coverage, the description provides the core purpose and a usage example. It omits important behavioral context like the result of extraction (what happens to the original location), dependency implications (e.g., update_imports behavior), and error conditions. Adequate but with clear gaps.

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 thoroughly. The description adds an example that illustrates how some parameters work together, but doesn't provide additional semantic meaning beyond what the schema provides. Baseline 3 is correct when schema does the heavy lifting.

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

Purpose4/5

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

States a specific verb+resource: extract a symbol (module, function, struct) to a separate file. This is clearly distinct from siblings like ast_move or ast_split, which handle different refactoring operations. However, it doesn't explicitly contrast itself with the closest alternatives, so it stops short of a 5.

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

Usage Guidelines2/5

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

The description offers no guidance on when to use this tool versus alternatives like ast_move or move_file. The example provides a concrete usage scenario but doesn't articulate when or when not to choose this operation.

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

ast_groupB
Destructive

Group symbols into a named module within a file. Creates the module if it doesn't exist, or appends to it. Example: {"path": "src/tests.rs", "module": "line_endings", "symbols": ["test_crlf", "test_lf"], "preamble": "use super::*;"}

NameRequiredDescriptionDefault
langNoLanguage hint.
pathYesFile to modify (relative to working directory).
moduleYesModule name to create or append to.
symbolsYesSymbols to move into the module.
positionNoWhere to place new module: "first-symbol" (default), "end", or "after:<symbol>".
preambleNoCode to insert at the top of the module (e.g., `use super::*;`).

TDQS

B3.2/5.0
Behavior3/5

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

Annotations already declare readOnlyHint=false and destructiveHint=true, so the mutation profile is covered. The description usefully adds that the module is created if missing or appended to, but does not warn that symbols are removed from their original location (the destructive effect) nor mention auth or reversibility.

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?

Two short sentences plus a compact JSON example, with the core behavior front-loaded. Efficient, though the example could be trimmed and no guidance sentences follow it.

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

Completeness3/5

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

With annotations carrying safety, 100% schema coverage, and no output schema, the description covers the essentials of what and how. It falls short on when-to-use versus the many AST siblings, leaving the selection decision to the agent.

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 six parameters including the position and lang fields the description ignores. The embedded example adds practical syntax for path/module/symbols/preamble but nothing beyond what the schema already conveys.

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

Purpose4/5

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

States a specific verb (group) and resource (symbols into a named module), and the phrase 'within a file' implicitly separates it from ast_extract_to_file and ast_move. Sibling differentiation exists but is not spelled out by name.

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

Usage Guidelines2/5

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

The description never says when to choose this tool over ast_wrap, ast_move, or ast_extract_to_file, nor any prerequisites or exclusions. Only the create-vs-append behavior is given, which is behavioral rather than routing guidance.

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

ast_impactB
Read-only

Transitive impact analysis: what symbols are affected by changing a given symbol. Traces the reference graph to find all direct and indirect dependents. Example: {"symbol": "parse_config", "path": "src/", "depth": 3}

NameRequiredDescriptionDefault
pathYesDirectory to scan for references (relative to working directory).
depthNoMaximum traversal depth (1 = direct refs only).
symbolYesSymbol name to analyze.

TDQS

B3.4/5.0
Behavior3/5

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

Annotations already declare readOnlyHint=true and openWorldHint=false, so the safety profile is covered. The description usefully clarifies that traversal is transitive (direct AND indirect dependents), which is real behavioral information, but says nothing about return shape, result size limits, or handling of cycles. Adequate but thin against the lowered bar.

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?

Three short sentences, front-loaded with the core purpose before the mechanism and example. The example is somewhat redundant given a fully described schema, but it is compact and does not bloat the text.

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

Completeness3/5

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

For a read-only traversal tool with no output schema, the description conveys what it computes (affected symbols) but not what the response looks like or how results are bounded. The essential inputs are covered by the schema, so nothing critical is missing, but a few gaps remain.

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 path, symbol, and depth are already documented, and the description's example merely restates those same three fields. Baseline 3 is appropriate; the description adds no format or semantics beyond the schema.

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

Purpose4/5

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

States a specific verb (transitive impact analysis) and resource (symbols affected by a change), plus the mechanism (traces the reference graph for direct and indirect dependents). It does not, however, distinguish itself from close siblings like ast_deps or ast_refs, which likely also traverse the reference graph.

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?

Usage is only implied through the worked example rather than stated: an agent can infer this is for 'what breaks if I change X' questions. There is no explicit when-to-use/when-not, no mention of when to prefer ast_deps or ast_refs instead, and no prerequisites noted.

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

ast_importsA
Destructive

Manage import/use statements: add (idempotent), remove, deduplicate. With no mutation args, lists existing imports. Example: {"path": "src/main.rs", "add": ["use std::collections::HashMap;"]}

NameRequiredDescriptionDefault
addNoImport statements to add (idempotent; skips if already present).
langNoLanguage hint.
pathYesFile to modify (relative to working directory).
dedupeNoDeduplicate imports.
removeNoImport statements to remove.

TDQS

A4.4/5.0
Behavior4/5

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

Annotations declare destructiveHint=true, and the description adds real context beyond them: add is idempotent (skips existing), and an empty mutation argument set degrades to a safe read — a nuance the readOnlyHint=false annotation alone would hide. It does not say whether formatting/ordering is preserved or how removal failures are reported.

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 dense sentences plus one short example; the operation set and the read-mode rule are front-loaded, and nothing is redundant with 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?

For a five-parameter mutation tool with no output schema, it covers modes, idempotency, and read behavior. It leaves unstated what a successful mutation returns and how a not-found removal is handled, which is a minor but real gap.

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, but the description adds semantics the schema lacks: the interaction rule that omitting add/remove/dedupe selects read mode, and the idempotency contract of add. The inline example also demonstrates the argument shape concretely.

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 resource (import/use statements) and enumerates the exact operations: add, remove, deduplicate, plus a read mode. This is clearly distinguishable from generic siblings like ast_insert or ast_replace, which do not target imports specifically.

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 an explicit mode-selection rule: 'With no mutation args, lists existing imports,' and flags that add is idempotent. It does not name which sibling to prefer for non-import edits, so the routing guidance is clear but not exhaustive.

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

ast_insertA
Destructive

Insert code at a structurally-aware position: inside a module/impl/struct (at start or end), or after/before a named symbol. Indentation is auto-detected. Example: {"path": "src/lib.rs", "content": "fn new_fn() {}", "after": "existing_fn"}

NameRequiredDescriptionDefault
langNoLanguage hint.
pathYesFile to insert code into (relative to working directory).
afterNoInsert after this symbol (mutually exclusive with inside/before).
beforeNoInsert before this symbol (mutually exclusive with inside/after).
insideNoModule/impl/struct to insert into (mutually exclusive with after/before).
contentYesCode to insert.
positionNoPosition within `inside`: "start" or "end" (default).

TDQS

A3.8/5.0
Behavior4/5

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

Annotations already declare destructiveHint=true and readOnlyHint=false, so the mutation profile is covered. The description adds a genuinely non-structured behavioral trait — indentation is auto-detected — which tells the agent the tool reformats rather than inserting raw text.

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 tight sentences plus a compact worked example, with the structural-positioning capability front-loaded ahead of the illustration. Nothing is padded.

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 mutation tool with no output schema and full annotation coverage, the description conveys positioning modes and indentation behavior adequately. It stops short of describing failure handling (e.g. target symbol not found) or whether surrounding code is reformatted.

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 all seven parameters are already documented with descriptions and mutual-exclusion notes; the baseline is 3. The description's example illustrates the after+content combination but adds no syntax or format detail beyond the schema.

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

Purpose4/5

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

Names a specific verb (insert) and resource (code) plus the structural positions it supports (inside module/impl/struct, before/after a named symbol). That clearly separates it from flat-file siblings like append_file or prepend_file, though it never names a sibling explicitly.

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 mode list implies when each targeting option applies, and the schema notes mutual exclusivity, but the description gives no explicit when-to-use/when-not guidance versus alternatives such as ast_replace_symbol or apply_patch.

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

ast_listA
Read-only

List symbol definitions (functions, classes, structs, enums, methods, etc.) in a file or directory. Supports 20 languages. Example: {"path": "src/"} or {"path": "main.py", "kind": "function,class"}

NameRequiredDescriptionDefault
kindNoFilter by symbol kind (comma-separated: function,struct,enum,class,method,trait,impl,const,type,interface,module).
langNoLanguage hint (overrides extension detection). E.g. "rs", "py", "go", "ts", "java", "c", "cpp".
pathYesFile or directory to list symbols from (relative to working directory).

TDQS

A3.6/5.0
Behavior3/5

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

Annotations already declare readOnlyHint=true and openWorldHint=false, so the safety profile is covered. The description adds that 20 languages are supported and what symbol kinds exist, but says nothing about output shape, result size on large directories, or pagination 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?

Two compact sentences with the core capability front-loaded, followed by concrete examples. No filler, though the trailing example block is somewhat redundant with the schema descriptions.

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 read-only listing tool with full schema coverage and no output schema, the definition covers purpose, scope, language support, and example invocations. Nothing essential for correct invocation is missing.

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

Parameters3/5

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

Schema description coverage is 100%, so all three parameters (path, kind, lang) are already documented in the schema, including the comma-separated kind list. The description's examples reinforce usage but add no syntax or format detail beyond what the schema provides, so the baseline of 3 applies.

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

Purpose4/5

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

States a specific verb and resource: 'List symbol definitions (functions, classes, structs, enums, methods, etc.) in a file or directory.' This clearly separates it from list_files (files, not symbols) and ast_search (search vs enumeration). It does not explicitly name a sibling alternative, so it stops short of a 5.

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 scope ('in a file or directory') implies when to reach for it, and the two inline examples show typical invocations. However, there is no explicit guidance on when to prefer ast_list over ast_search, ast_map, or ast_read, nor any stated prerequisites.

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

ast_mapB
Read-only

Generate a ranked repository map using PageRank over the symbol reference graph. Shows the most important symbols with token-budget-aware output. Example: {"path": "src/", "max_tokens": 2048}

NameRequiredDescriptionDefault
pathYesDirectory to map (relative to working directory).
boostNoBoost these symbol names (comma-separated).
focusNoBoost symbols from these files (comma-separated paths).
max_tokensNoMaximum approximate token count for output.

TDQS

B3.2/5.0
Behavior3/5

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

Annotations already declare readOnlyHint=true and openWorldHint=false, so the safety profile is covered. The description usefully adds the ranking algorithm and the token-budget-aware nature of output, but never describes the shape of the returned map or how ranking/boost/focus actually affect results.

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?

Three tight sentences, purpose front-loaded and the example placed last. Nothing wasteful, though the example occupies space that could have carried guidance on the optional boost/focus parameters.

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

Completeness3/5

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

For a read-only tool with no output schema, the description covers what it does and its mechanism, but leaves open what the 'map' actually looks like in the response and how ranking/boost interact. Adequate but with a visible gap for an agent that must interpret the output.

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 all four parameters are already documented in the schema, setting the baseline at 3. The inline example of path + max_tokens adds a little concrete usage guidance, but boost and focus receive no extra explanation in the description.

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

Purpose4/5

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

States a specific verb ('Generate') plus resource ('ranked repository map') and even the mechanism ('PageRank over the symbol reference graph'), so the agent knows exactly what it produces. However it does not name or contrast any sibling (e.g. ast_deps, ast_impact, ast_refs) that an agent might confuse it with.

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

Usage Guidelines2/5

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

'Shows the most important symbols' hints at intent, but there is no explicit when-to-use, when-not-to-use, or alternative routing among the many ast_* siblings. The agent is left to infer whether this replaces ast_impact or ast_search.

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

ast_moveB
Destructive

Move symbols between files. Removes from source, inserts into target (creating it if needed). Example: {"path": "src/big.rs", "target": "src/helpers.rs", "symbols": ["helper_fn"], "target_prepend": "use super::*;"}

NameRequiredDescriptionDefault
langNoLanguage hint.
pathYesSource file (relative to working directory).
targetYesTarget file.
symbolsYesSymbols to move.
positionNoPosition in target: "end" (default), "start", "after:<symbol>", "before:<symbol>".
target_prependNoContent to prepend to target file if creating it.
update_importsNoRewrite consumer `use`/import statements of moved symbols.
new_module_pathNoModule path consumers should import from (required with `update_imports`).
old_module_pathNoModule path consumers currently import from (required with `update_imports`).

TDQS

B3.2/5.0
Behavior3/5

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

Annotations already declare destructiveHint=true and readOnlyHint=false, covering the safety profile. The description adds that the target is created if needed and that the source is mutated, which is useful. It omits auth/permission needs, collision/overwrite behavior when the target already contains the symbol, and the fact that update_imports requires new_module_path/old_module_path.

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?

Two sentences plus a compact JSON example, front-loaded with the core action. Efficient, though the example chooses a lesser-used parameter rather than the required trio.

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

Completeness3/5

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

For a destructive 9-parameter mutation with no output schema, the description is workable but thin: no return semantics, no mention of conflict/overwrite outcomes, no indication that update_imports has coupled required params. Annotations carry the safety signal, keeping this at minimum viable.

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 9 parameters, including position enum-likes and the module-path dependency. The description only illustrates target_prepend, adding marginal value. Baseline 3 applies.

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

Purpose4/5

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

States a specific verb (Move) and resource (symbols between files), and clarifies the two-part effect (removes from source, inserts into target). It doesn't explicitly distinguish itself from siblings like ast_extract_to_file, ast_insert, or move_file, but the symbol-level scope is clear.

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

Usage Guidelines2/5

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

No when-to-use guidance, no conditions selecting this over ast_extract_to_file / ast_insert / move_file, and no prerequisites called out. The example implies typical usage but does not state exclusions or alternatives.

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

ast_readA
Read-only

Read a specific symbol's source code by name from a file. Uses AST parsing to find the exact definition. Example: {"path": "src/main.rs", "symbol": "run"}

NameRequiredDescriptionDefault
langNoLanguage hint.
pathYesFile to read from (relative to working directory).
symbolYesSymbol name (e.g. "run" or "Server::start").
contextNoNumber of context lines before/after the symbol.

TDQS

A3.8/5.0
Behavior3/5

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

Annotations already declare readOnlyHint=true and openWorldHint=false, so safety is covered. The description usefully adds that resolution is AST-based and exact rather than textual, but it does not say what happens when the symbol is not found, whether partial matches are returned, or how 'context' interacts with symbol boundaries.

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 sentences plus a compact inline example, front-loaded with the core action and mechanism. Every element earns its place and nothing is padded.

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 tool with fully documented parameters and no output schema, the description covers purpose and resolution mechanism adequately. The one residual gap is return-shape ambiguity (exact definition only vs. surrounding lines), which matters slightly more because no output schema exists to clarify it.

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 all four parameters (lang, path, symbol, context) are already documented in the schema, and the baseline is 3. The description's example reinforces the path/symbol pairing and the symbol syntax ('run'), but adds nothing about lang hints or context line 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 states a specific verb (Read), a precise resource (a specific symbol's source code), the input (by name from a file) and the mechanism (AST parsing to find the exact definition). This clearly distinguishes it from whole-file readers like read_file and from search-style siblings such as ast_search.

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?

Usage is implied by the 'by name' framing and demonstrated by the inline example, but there is no explicit when-to-use/when-not guidance and no named alternative (e.g. read_file for whole files, ast_search when the symbol name is unknown). An agent must infer the selection criteria.

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

ast_refsA
Read-only

Find all references to a symbol across files using AST analysis. Distinguishes definitions from references. Example: {"symbol": "process_data", "path": "src/"}

NameRequiredDescriptionDefault
langNoLanguage hint.
pathYesFile or directory to search (relative to working directory).
symbolYesSymbol name to find references for.
include_defNoInclude the definition site in results.

TDQS

A3.7/5.0
Behavior3/5

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

Annotations already declare readOnlyHint=true and openWorldHint=false, covering the safety profile. The description adds the useful behavioral note that definitions are distinguished from references, but doesn't disclose result format or whether recursive search occurs, leaving it at baseline-plus.

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?

Two sentences plus an example, front-loaded with the core purpose. Efficient, though the JSON example is somewhat verbose relative to the payload it conveys.

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 reference-finding tool with full schema coverage and annotations, the description is nearly complete. It could note how definitions are marked in output, but no output schema exists so that gap is minor.

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 fully documents all four parameters. The example confirms symbol/path usage but adds no semantics beyond the schema's own descriptions. Baseline 3 applies.

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

Purpose5/5

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

States a specific verb+resource ('Find all references to a symbol') and explicitly distinguishes from definitions ('Distinguishes definitions from references'), which differentiates it from siblings like ast_search or ast_impact.

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 implies usage (finding symbol references) but offers no explicit when/when-not guidance or named alternatives among the many ast_* siblings. The inline example clarifies invocation but not tool selection.

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

ast_renameA
Destructive

Rename identifiers across files using AST-aware renaming (skips strings and comments). Example: {"path": "src/", "old": "process_data", "new": "transform_data"}

NameRequiredDescriptionDefault
newYesThe new identifier name (same name as replace / plan `new`). Alias `to` accepted because agents often emit that name (LLM prior).
oldYesThe identifier to rename (same name as replace / plan `old`). Alias `from` accepted because agents often emit that name (LLM prior).
langNoLanguage hint.
pathYesFile or directory to rename in (relative to working directory).

TDQS

A3.6/5.0
Behavior4/5

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

Annotations already flag this as destructive and non-read-only. The description adds genuinely non-obvious behavior beyond that: it is AST-aware and explicitly skips strings and comments, and it operates 'across files.' It still omits reversibility/undo and confirmation of in-place file writes, keeping it short of a 5.

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?

One front-loaded sentence with the key constraint (skips strings/comments) followed by a compact example. No filler; every element is functional.

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 4-param mutation tool with no output schema and full schema coverage, the definition is nearly sufficient: it conveys scope and semantic behavior. The remaining gap is that it never states that files are modified on disk or how to verify/undo the change.

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%, and the schema even documents the from/to aliases, so the baseline is 3. The example maps path/old/new to a concrete call, but adds no semantics (e.g., lang, alias behavior) beyond what the schema already provides.

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

Purpose4/5

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

States a specific verb and resource ('Rename identifiers across files') and adds the differentiator 'AST-aware... skips strings and comments.' However, it never contrasts itself with close siblings like ast_replace, ast_replace_symbol, or replace_text, which is exactly the confusion an agent would have here.

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

Usage Guidelines2/5

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

The description implies the basic use case (rename an identifier) but gives no when-to-use/when-not guidance and names no alternatives. With sibling tools such as ast_replace, ast_replace_symbol, and replace_text, the agent is left to guess which renaming tool to select.

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

ast_reorderB
Destructive

Reorder symbols within a file or scope by name, kind, or custom order. Example: {"path": "src/lib.rs", "order": "alphabetical"} or {"path": "src/lib.rs", "order": ["Struct", "impl Struct", "helper"], "inside": "mod tests"}

NameRequiredDescriptionDefault
langNoLanguage hint.
pathYesFile to reorder symbols in (relative to working directory).
orderYesOrdering: "alphabetical", "reverse", "kind-first", or array of names.
insideNoScope to reorder within (module/impl). Default: top-level.

TDQS

B3.2/5.0
Behavior3/5

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

Annotations already declare destructiveHint=true and readOnlyHint=false, so the mutation profile is covered structurally. The description adds the notion of scoping (file vs. nested scope) but says nothing about what gets rewritten, whether comments/formatting are preserved, or whether the operation is reversible — useful additions the annotations do not supply.

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?

Purpose is front-loaded in the first sentence, followed by two compact examples that carry real information. No filler text, though the examples are somewhat dense inline.

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

Completeness3/5

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

For a destructive mutation tool with no output schema, the description covers what and how but omits safety-relevant context such as reversibility, permission needs, or whether unrelated file content is preserved. Adequate but with clear gaps for a write operation.

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 four parameters. The examples reinforce the shape of 'order' (a keyword like 'alphabetical' vs. an array of names) and the interaction with 'inside', but add no semantics beyond what the schema provides, so the baseline 3 applies.

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

Purpose4/5

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

States a specific verb (reorder), resource (symbols within a file or scope), and the ordering criteria (name, kind, or custom order). It is clear on its own, but it never names a sibling like ast_move or ast_group, so the agent must infer the boundary between reordering and moving/grouping from other tools.

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

Usage Guidelines2/5

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

The two examples illustrate the mechanics of calling the tool, but nothing states when to choose ast_reorder over ast_move, ast_split, or ast_group, nor any prerequisites such as a clean/parseable file. There is no when-to-use or when-not guidance at all.

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

ast_replaceA
Destructive

Replace text only within a specific symbol's body using AST scoping. Precise: only changes code inside the named symbol, leaving everything else untouched. Example: {"path": "src/lib.rs", "symbol": "parse_config", "old": "unwrap()", "new": "expect("parse failed")"}

NameRequiredDescriptionDefault
newYesReplacement text. Alias `to` accepted because agents often emit that name (LLM prior).
oldYesText or regex pattern to find. Alias `from` accepted because agents often emit that name (LLM prior).
langNoLanguage hint.
pathYesFile containing the symbol (relative to working directory).
regexNoTreat `old` as a regex pattern.
symbolYesSymbol name to scope the replacement to.

TDQS

A3.9/5.0
Behavior4/5

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

Annotations already declare destructiveHint=true / readOnlyHint=false, so the safety profile is known, but the description adds real value by bounding the blast radius: 'only changes code inside the named symbol, leaving everything else untouched.' It still omits failure behavior (e.g., symbol not found, no match) and regex semantics, which keeps it from a 5.

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?

Front-loaded with the purpose, then the scoping guarantee and a compilable example. The second sentence slightly restates the first ('only within symbol's body' vs. 'only changes code inside the named symbol'), so it is efficient but not perfectly tight.

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 6-param destructive tool with no output schema, the description covers scope and usage form well and annotations carry the safety profile. It leaves gaps around error/no-match behavior and how the regex flag interacts with symbol scoping.

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 every parameter including aliases. The example usefully shows path/symbol/old/new used together, but the description adds no extra semantics (e.g., regex + symbol interaction) beyond the schema, making the baseline 3 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?

States a specific verb (replace) with a precise scope (text only within a named symbol's body, via AST scoping) that distinguishes it from generic siblings like replace_text and from ast_replace_symbol. The example makes the operation concrete and actionable.

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 implies when to use it (scoped, symbol-local replacement vs. whole-file replacement), but never names an alternative tool or states a when-not condition. An agent must infer that replace_text is the unscoped counterpart rather than being told.

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

ast_replace_symbolB
Destructive

Replace a whole symbol span, including leading doc comments and attributes, with new source re-indented to the symbol column. Replaces the full symbol span (docs and attributes included). Example: {"content":"fn default_timeout() -> u64 { 60 }","path":"src/lib.rs","symbol":"default_timeout"}

NameRequiredDescriptionDefault
langNoLanguage hint (e.g. "rust", "go"). Overrides extension-based detection.
pathYesFile containing the symbol.
symbolYesSymbol name to replace (qualified names like `Impl::method` accepted).
contentYesReplacement source for the full symbol span.
agent_presetNoWhen true, replace uses the agent preset: unique, require_change, fuzzy floor 0.90, allow_absent_old false. Off unless set.
expected_sha256NoSHA-256 hex of the file's current bytes. If it does not match, the tool returns error_kind stale and writes nothing.

TDQS

B3.3/5.0
Behavior4/5

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

Annotations already declare destructiveHint=true and readOnlyHint=false, so safety is covered. The description adds real value beyond that: it discloses that the replaced span includes leading doc comments and attributes (i.e. those will be destroyed) and that replacement source is re-indented to the symbol column. It still omits failure behavior when the symbol is absent.

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

Conciseness3/5

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

Front-loaded and the example earns its place, but the second sentence ('Replaces the full symbol span (docs and attributes included)') is near-verbatim repetition of the first, wasting a quarter of the text.

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

Completeness3/5

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

For a destructive 6-parameter mutation tool with no output schema, the description covers the core span semantics but says nothing about failure modes (missing symbol, stale hash) or what a successful response contains. Adequate as a minimum, not complete.

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

Parameters3/5

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

Schema description coverage is 100%, so the baseline is 3; the schema already documents path, symbol, content, lang, agent_preset and expected_sha256. The description adds only that the replaced span is the whole symbol, which partly restates the schema's own top-level description, and the example demonstrates required-parameter usage without adding format rules.

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

Purpose4/5

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

States a specific verb+resource ('Replace a whole symbol span') and qualifies the scope as including leading doc comments and attributes, which separates it from a plain text replace. It does not explicitly name the sibling it differs from (e.g. ast_replace or ast_rewrite_signature), so the differentiation is left to inference.

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

Usage Guidelines2/5

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

No when-to-use, when-not-to-use, or alternative-selection guidance is given. The embedded example shows how to call it but not when to prefer it over ast_replace, ast_rewrite_signature, or apply_patch.

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

ast_rewrite_signatureB
Destructive

Rewrite a function signature with structured fields (visibility, parameters, return_type) or a full new_signature string. Multi-language via tree-sitter. Example: {"path": "src/lib.rs", "old": "process", "parameters": "(x: i32)", "return_type": "-> String"}

NameRequiredDescriptionDefault
oldYesFunction name to rewrite. Aliases `name`/`from` accepted for agents.
langNoLanguage hint.
pathYesFile containing the function (relative to working directory).
parametersNoNew parameter list including parens.
visibilityNoNew visibility (e.g. "pub", "pub(crate)", or "").
return_typeNoNew return type using language-native syntax.
new_signatureNoFull replacement signature text (optional). Alias `to` for agents.

TDQS

B3.2/5.0
Behavior2/5

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

Annotations already declare destructiveHint=true, readOnlyHint=false and openWorldHint=false, so the safety profile is covered. The description adds only 'multi-language via tree-sitter' and an example; it never says whether the function body is preserved, whether the edit is atomic/undoable, or how conflicting matches are handled, which is thin for a destructive mutation.

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?

Purpose is front-loaded in the first clause, the two input modes follow, and the JSON example earns its place by showing required keys and formatting. Three sentences with little waste, though the example duplicates schema content.

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

Completeness3/5

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

For a destructive 7-parameter tool with no output schema, the description covers the input shape but omits failure/ambiguity behavior, body-preservation guarantees, and how structured fields interact with new_signature. Adequate but with clear gaps an agent would hit in practice.

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 every parameter is already documented, and the baseline is 3. The description reiterates the field names and shows a concrete example, but adds no precedence rule between the structured fields and new_signature, nor semantics the schema lacks.

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

Purpose4/5

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

States a specific verb+resource (rewrite a function signature) and names the exact structured fields involved, so the operation is unambiguous. It does not, however, differentiate itself from close siblings like ast_rename or ast_replace_symbol, which an agent must choose between.

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 implicitly tells the agent it may either supply structured fields or a full new_signature string, which is real mode-selection guidance. It offers no when-to-use vs. alternatives (ast_rename, ast_replace_symbol), no prerequisite conditions, and no note on what happens if the named function is absent or ambiguous.

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

ast_splitA
Destructive

Split a file into multiple target files by distributing symbols. Atomic: all targets succeed or all roll back. Example: {"source": "src/big.rs", "targets": [{"path": "src/types.rs", "symbols": ["Config", "Mode"], "prepend": "use super::*;"}], "keep_in_source": ["main"], "source_suffix": "mod types;"}

NameRequiredDescriptionDefault
langNoLanguage hint.
sourceYesThe file to split.
targetsYesTarget file specs.
source_prefixNoText to prepend to source after split.
source_suffixNoText to append to source after split (e.g., `mod` declarations).
keep_in_sourceNoSymbols to keep in the source file.
require_exhaustiveNoError if any symbol is unaccounted for (default: true).

TDQS

A3.8/5.0
Behavior4/5

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

Annotations already declare readOnlyHint=false and destructiveHint=true, so the mutation risk is covered structurally. The description adds genuinely useful context beyond that: 'Atomic: all targets succeed or all roll back,' which tells the agent the operation is transactional and safe to retry on failure — a real behavioral trait not derivable from annotations.

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?

Front-loaded purpose sentence, then the atomicity guarantee, then a dense JSON example. No filler text; the example is long but carries parameter-interaction information that would otherwise be prose. Structure is appropriate for a 7-parameter mutation 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 destructive multi-file mutation with no output schema, the description covers the essential risk (atomic rollback) and demonstrates a realistic invocation. It does not describe what the agent receives on success/failure or the effect of unlisted symbols, though require_exhaustive is documented in the schema.

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 and the schema already documents every parameter. The worked example goes further by showing how the parameters interlock — distributing named symbols across targets, keeping 'main' in source, and using source_suffix for a 'mod types;' declaration — which clarifies the relationship between keep_in_source, targets, and source_suffix that the flat schema does not convey.

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

Purpose4/5

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

States a specific verb and resource with mechanism: 'Split a file into multiple target files by distributing symbols.' The 'multiple target files' framing implicitly separates it from single-target siblings like ast_extract_to_file or ast_move, but no sibling is named explicitly, so the differentiation is inferential rather than stated.

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 and its worked example imply when this tool applies (a large file whose symbols should be distributed into modules), but there is no explicit when-to-use versus ast_extract_to_file/ast_move guidance, no prerequisites, and no statement of when to prefer a different sibling.

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

ast_validateA
Read-only

Validate syntax of source files. Returns parse errors with line numbers. Supports 20 languages. Example: {"path": "src/main.rs"}

NameRequiredDescriptionDefault
langNoLanguage hint.
pathYesFile or directory to validate syntax (relative to working directory).

TDQS

A3.5/5.0
Behavior4/5

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

Annotations already declare readOnlyHint=true and openWorldHint=false, so safety is covered. The description adds genuinely new behavioral context beyond that: the return shape ("parse errors with line numbers") and language coverage (20 languages), which matters since there is no output schema.

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?

Four short sentences, front-loaded with the purpose and followed by the return value, language scope, and a concrete call example. No filler, though the example is somewhat redundant with 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?

For a read-only, two-parameter tool whose annotations carry the safety profile, the description covers purpose, return content, and language scope. The main open question is directory handling (does a directory path recurse, and does it stop at first error?), which neither the description nor schema clarifies.

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 both parameters are already documented (path as file or directory, lang as a language hint). The description's example illustrates the path format but adds no semantics the schema lacks. Baseline 3 is appropriate.

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

Purpose4/5

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

States a specific verb+resource ("Validate syntax of source files") and adds scope detail (20 languages, parse errors with line numbers). It does not name any sibling to differentiate from, though the validate/lint niche is reasonably distinct from the mutation-heavy ast_* family.

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

Usage Guidelines2/5

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

No when-to-use, when-not-to-use, or alternative guidance is given. The description never mentions related tools like md_lint, tidy_check, or fix_whitespace, so the agent must infer that this is the pre-edit syntax check.

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

ast_wrapB
Destructive

Wrap existing code in a structural block (module, impl, cfg, etc.). Specify symbols by name or a line range. Example: {"path": "src/lib.rs", "symbols": ["helper_fn", "HelperStruct"], "wrapper": "mod helpers"}

NameRequiredDescriptionDefault
langNoLanguage hint.
pathYesFile to modify (relative to working directory).
linesNoLine range to wrap (e.g. "10:50", mutually exclusive with symbols).
symbolsNoSymbols to wrap (mutually exclusive with lines).
wrapperYesThe wrapping construct (e.g. "mod foo", "impl Bar", "#[cfg(test)]").
preambleNoContent to insert at the top of the wrapped block.

TDQS

B3.4/5.0
Behavior3/5

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

Annotations declare destructiveHint=true and readOnlyHint=false, so the mutation risk is already conveyed. The description adds the 'structural block' concept and mutual exclusivity detail, which is useful. But for a destructive, non-idempotent mutation, it doesn't disclose whether the operation is reversible (e.g., via undo), whether it preserves formatting, or any file-modification side effects. This is a moderate gap.

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?

Three sentences, front-loaded with the core operation, then selection mode, then a concrete example. No obfuscation. Slightly more verbose than a minimal description but every element serves clarity.

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

Completeness3/5

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

For a destructive mutation with no output schema and 100% schema coverage, the description covers purpose and mechanics adequately. However, it omits critical context for a destructive tool: whether wrapping is reversible, what happens to existing comments/formatting, and any error conditions (e.g., overlapping wrappers). The annotations flag destruction but don't compensate for these omissions.

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 both required and optional parameters are fully documented in the schema. The description reinforces the two selection modes (symbols vs lines) and provides an example, which adds marginal value. Baseline 3 is appropriate when the schema does the heavy lifting.

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

Purpose4/5

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

States a specific verb+resource: 'Wrap existing code in a structural block (module, impl, cfg, etc.).' This clearly differentiates from siblings like ast_insert (insert new code), ast_group, and ast_rewrite_signature. However, it doesn't explicitly name a sibling it's distinguished from, so a 4 rather than 5.

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 gives implied usage through the example and mentions specifying symbols by name or line range, but offers no explicit when-to-use/when-not-to-use guidance or named alternatives (e.g., vs ast_group or ast_insert). It relies on inference.

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

batch_replaceA
Destructive

Replace the same text across multiple files in one call. Engine staging is atomic for applied writes (all written files succeed or none change). Pattern misses are soft by default: matching files still apply and total misses appear in refused[]; set require_change=true to fail the whole batch if any file has no match. Canonical field is files (array); singular file is accepted as an alias for one path. Optional fuzzy enables similarity fallback; when exact old is absent, refuse by default unless allow_absent_old=true (#1758). JSON reports match_mode (exact/fuzzy/anchored), optional match_score, optional matched_text, match_count per change and aggregate (#1674). Example: {"files": ["Cargo.toml", "README.md"], "old": "0.1.0", "new": "0.2.0"}

NameRequiredDescriptionDefault
newYesText to replace with. Alias `to` accepted because agents often emit that name (LLM prior).
oldYesText to find in each file. Alias `from` accepted because agents often emit that name (LLM prior).
fileNoSingle file (LLM prior). Equivalent to `files: [file]` when `files` is empty. If both are set, `files` wins. Alias `path` matches replace_text priors.
filesNoFile paths to apply the replacement to (relative to working directory). Canonical multi-file form.
fuzzyNoWhen exact match fails, try fuzzy/similarity fallback (#1668).
regexNoUse regex mode for the `old` pattern.
strictNoRoll back all writes when format/validate lifecycle steps fail.
if_existsNoIf true, silently succeed when a file does not contain the pattern instead of returning an error. Useful for idempotent batch replacements.
multilineNoEnable multiline matching (dot matches newlines in regex mode).
word_boundaryNoMatch only at word boundaries. Prevents 'SetupFile' from matching inside 'BenchSetupFile'. Auto-escapes regex metacharacters.
require_changeNoFail when a file has zero matches (fail closed). Softened when if_exists is true.
min_fuzzy_scoreNoReject fuzzy matches below this similarity floor (#1687). `None` = no floor.
allow_absent_oldNoAllow fuzzy apply when exact `old` is absent (#1758). Default false (fail closed; report best candidate without writing).
case_insensitiveNoCase-insensitive matching.
command_positionNoOnly rewrite shell command-position tokens (not arguments / longer words). Peels wrappers like sudo, timeout, busybox, flock, runuser, setsid.

TDQS

A4.1/5.0
Behavior5/5

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

Annotations only say this is a destructive, non-read-only write; the description adds the substantive traits an agent needs: engine staging is atomic for applied writes (all succeed or none change), misses are soft by default, absent `old` refuses by default, and the JSON report shape (match_mode, match_score, matched_text, match_count, refused[]). That is real disclosure beyond the annotation layer.

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?

Front-loaded with purpose and the atomicity guarantee, then behavior, then example — good ordering with no filler sentences. The inline issue references (#1758, #1674, #1668, #1687) are clutter that costs tokens without helping the agent.

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 15-parameter destructive tool with no output schema, the description covers the essentials: atomicity semantics, default failure policy, opt-in flags, alias precedence, and the shape of the returned JSON including the refused[] miss channel. An agent has enough to call it correctly without opening the schema.

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

Parameters3/5

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

Schema description coverage is 100%, so the baseline is 3, and most description content (files vs file alias, fuzzy, allow_absent_old, require_change) restates what the schema already documents. The one genuine addition is the worked example showing a minimal valid call, which alone does not lift it above baseline.

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

Purpose4/5

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

Opens with a specific verb + resource + scope: 'Replace the same text across multiple files in one call,' which immediately separates it from single-file replace_text and from patch-style siblings. It never names the alternative tool explicitly, so the distinction is inferred from 'multiple files' rather than stated.

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 concrete conditional guidance for the important switches: soft-miss default with require_change=true to fail the whole batch, and refuse-by-default when exact `old` is absent unless allow_absent_old=true. It does not, however, tell the agent when to pick batch_replace over replace_text or apply_patch, so tool selection is left implicit.

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

batch_tidyA
Destructive

Fix whitespace in multiple files in one call: trims trailing spaces and ensures final newline. Atomic: all files succeed or none change. Canonical field is files (array); singular file is accepted as an alias for one path. Example: {"files": ["src/main.rs", "src/lib.rs"]}

NameRequiredDescriptionDefault
fileNoSingle file (LLM prior). Equivalent to `files: [file]` when `files` is empty. If both are set, `files` wins. Alias `path` matches other tools.
filesNoFile paths to normalize (relative to working directory). Canonical multi-file form.
strictNoRoll back all writes when format/validate lifecycle steps fail.

TDQS

A3.9/5.0
Behavior4/5

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

Annotations already declare destructiveHint=true and readOnlyHint=false, so the mutation profile is known. The description adds meaningful context beyond that: transactional 'all files succeed or none change' atomicity, which is important for an agent deciding whether partial failure is possible. It does not describe error reporting or how failures surface, but the atomicity disclosure is a real contribution.

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?

Front-loaded with the operation, followed by atomicity guarantees, then parameter guidance and an example. Four sentences with little waste, though the alias sentence repeats what the schema already states, slightly diluting density.

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 mutation tool with no output schema, the definition covers the operation, atomicity, and argument forms, which is most of what an agent needs. It stops short of describing success/failure reporting, the only notable gap given there is no output schema to carry that.

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% and the schema already documents the files/file alias relationship and precedence ('files wins'). The description restates the canonical-vs-alias distinction and adds a concrete example, but this largely duplicates structured data, so 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?

States a specific verb and resource (fix whitespace in multiple files) and names the exact transformations performed: trims trailing spaces and ensures final newline. This distinguishes it from the sibling fix_whitespace (single file) and tidy_check (check-only) even without opening their schemas.

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 phrase 'multiple files in one call' implies the batch context, but it never explicitly tells the agent when to prefer this over fix_whitespace, tidy_check, or batch_replace, nor does it state exclusions. Usage must be inferred from the implied batch semantics.

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

create_fileA
Destructive

Create a new file with specified content. Fails if the file exists unless force=true. Example: {"content":"{"version": "1.0"}","path":"config.json"}

NameRequiredDescriptionDefault
pathYes
forceNo
contentYes
agent_presetNoWhen true, replace uses the agent preset: unique, require_change, fuzzy floor 0.90, allow_absent_old false. Off unless set.
expected_sha256NoSHA-256 hex of the file's current bytes. If it does not match, the tool returns error_kind stale and writes nothing.

TDQS

A4/5.0
Behavior4/5

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

Annotations already declare readOnlyHint=false and destructiveHint=true, so the safety profile is covered and the bar is lower. The description adds genuinely new context — the existing-file failure mode and the force override — which the annotations do not convey.

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?

Purpose is front-loaded, followed by the key behavioral caveat, then a compact usage example. Every element earns its place with no padding.

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 5-param destructive write tool with no output schema, the description covers the core create/force behavior and gives an example. It omits any mention of expected_sha256 stale handling or agent_preset interaction, though those are documented in the schema.

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 40% (low), so the description should compensate. It explains force semantics and demonstrates path/content values via the example, but path/content semantics are never described in prose, and agent_preset/expected_sha256 are left entirely to 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+resource ("Create a new file with specified content"). The word "new" implicitly distinguishes it from append_file/prepend_file siblings, so an agent can route correctly without opening a schema.

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?

"Fails if the file exists unless force=true" gives a conditional on the force flag, which is borderline behavioral rather than usage guidance. It never names alternatives (append_file, prepend_file, apply_fragment) or says when to prefer this tool, so guidance is only implied.

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

delete_fileA
Destructive

Delete a file. Default fails with not_found if the path is missing. Set if_exists=true to soft-skip a missing file (no write, success). Set if_exists=true to soft-skip when the file is missing. Example: {"path":"tmp/scratch.txt"}

NameRequiredDescriptionDefault
pathYesPath of the file to delete.
if_existsNoSoft-skip (no write) when the file is missing. Default false: missing path is `not_found`.
agent_presetNoWhen true, replace uses the agent preset: unique, require_change, fuzzy floor 0.90, allow_absent_old false. Off unless set.
expected_sha256NoSHA-256 hex of the file's current bytes. If it does not match, the tool returns error_kind stale and writes nothing.

TDQS

A3.6/5.0
Behavior4/5

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

Annotations already declare destructiveHint=true and readOnlyHint=false, so safety is covered structurally. The description adds genuinely useful error semantics (default not_found on a missing path; if_exists soft-skips with a success and no write), which the agent cannot infer from the schema alone. It stops short of covering rollback or the concurrency implications of the SHA parameter.

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

Conciseness3/5

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

The lead sentence is appropriately front-loaded, but the middle content is redundant: the if_exists=true soft-skip instruction is stated twice in near-identical wording. The example is compact and helpful, but the duplicated sentence is wasted space.

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?

With destructive annotations and a fully documented schema, the description only needs to supply the missing-file behavior, which it does. That plus the example is sufficient for an agent to call the tool correctly, though the leftover duplication and silence on expected_sha256/stale behavior keep it from being fully polished.

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 four parameters including if_exists. The description restates the if_exists behavior rather than adding syntax or format meaning, so it does not exceed the schema baseline.

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

Purpose4/5

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

The opening 'Delete a file' states a specific verb and resource, making the action unambiguous among siblings like move_file and create_file. It does not, however, explicitly differentiate itself from any alternative tool; the clarity comes from the nature of 'delete' rather than comparative framing.

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 explains the default missing-path failure and offers if_exists=true as a soft-skip, which is a conditional usage nuance. It never states when to prefer this tool over siblings or any preconditions for the destructive delete, leaving usage only implied.

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

doc_appendB
Destructive

Append a value to an array at a selector path. Example: {"value":"new_item","path":"data.json","selector":"items"}

NameRequiredDescriptionDefault
pathYesPath to the JSON, YAML, or TOML file.
valueYesValue to append to the array.
selectorYesDot-notation selector path to an array.
agent_presetNoWhen true, replace uses the agent preset: unique, require_change, fuzzy floor 0.90, allow_absent_old false. Off unless set.
expected_sha256NoSHA-256 hex of the file's current bytes. If it does not match, the tool returns error_kind stale and writes nothing.

TDQS

B3.1/5.0
Behavior2/5

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

Annotations already declare readOnlyHint=false, destructiveHint=true, and openWorldHint=false, so the safety profile is covered. The description adds essentially nothing beyond that: it does not say what happens if the selector path is not an array, whether the file is created when absent, that writes are destructive/irreversible, or how expected_sha256 staleness is surfaced.

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?

One terse sentence plus one inline example, front-loaded with the core action. Nothing is wasted and the example compactly demonstrates parameter shape.

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

Completeness3/5

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

For a destructive array mutation the description is thin, but annotations carry the safety signal and the schema fully documents all five parameters including stale-write protection. Missing is any note on edge-case behavior (non-array selector, absent file) that an agent would want before a destructive write.

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 path, value, selector, agent_preset, and expected_sha256 are all documented in the schema. The description's example reinforces the three required params but adds no format or constraint detail beyond what the schema already provides, which is the baseline 3.

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

Purpose4/5

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

The description gives a precise verb+resource: append a value to an array at a selector path. This is clearly distinguishable from sibling mutations like doc_prepend, doc_set, doc_merge, and doc_delete. It stops short of naming a sibling to contrast against, but the operation itself is specific.

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

Usage Guidelines2/5

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

There is a concrete example showing the three required parameters in use, but no statement of when to reach for doc_append versus doc_prepend, doc_set, or doc_update, and no exclusions or prerequisites. The agent is left to infer usage purely from the verb.

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

doc_deleteA
Destructive

Delete a value at a selector path in a JSON, YAML, or TOML file. CLI --json and MCP/tx success include changed and removed (0 on missing key; exit 0 / ok is idempotent). Example: {"selector":"deprecated_key","path":"config.json"}

NameRequiredDescriptionDefault
pathYesPath to the JSON, YAML, or TOML file.
selectorYesDot-notation selector path to delete.
agent_presetNoWhen true, replace uses the agent preset: unique, require_change, fuzzy floor 0.90, allow_absent_old false. Off unless set.
expected_sha256NoSHA-256 hex of the file's current bytes. If it does not match, the tool returns error_kind stale and writes nothing.

TDQS

A3.9/5.0
Behavior4/5

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

Annotations already declare destructiveHint=true and readOnlyHint=false, so the safety profile is covered. The description adds genuinely useful behavior not in the annotations: the success payload carries changed/removed counts, deleting a missing key is idempotent (removed=0, exit 0/ok), which prevents an agent from mistaking a no-op for a failure.

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?

Purpose is front-loaded in the first sentence and the total length is appropriate for a mutation tool. The middle sentence about 'CLI --json and MCP/tx' is tersely worded and slightly cryptic, but not wasteful.

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 mutation with no output schema, the description covers the important return semantics (changed/removed, idempotent no-op) and the schema covers the concurrency guard via expected_sha256. It omits any note on permission requirements or revertibility (undo_list/undo_restore exist as siblings), which is the only real gap.

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 path, selector, expected_sha256, and agent_preset are all documented in the schema; baseline is 3. The description only echoes path/selector via the example and adds no syntax detail (e.g. how to escape dots in a key name) beyond what the schema already provides.

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

Purpose5/5

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

States a specific verb (delete), the exact resource (a value at a selector path), and the supported file formats (JSON, YAML, TOML). The 'selector path' framing implicitly separates it from the predicate-based sibling doc_delete_where and from whole-file siblings such as delete_file.

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 shows a concrete invocation example, so usage is implied, but it never states when to reach for this tool over doc_delete_where, delete_file, or ast_delete_symbol, and gives no exclusions or preconditions. An agent must infer the selection from sibling names alone.

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

doc_delete_whereA
Destructive

Delete array elements matching a key=value predicate via --predicate (CLI) or the predicate field (plans). For scalar arrays use .=x, =x, or value=x. Different from doc.update, which filters inside the selector path. CLI --json and MCP/tx success include changed and removed (0 when no elements match; exit 0 / ok is idempotent). For object arrays: predicate='role=admin'. For simple arrays: predicate='=value'. Nested paths: predicate='settings.theme=dark'. Example: {"predicate":"value=a","path":"config.toml","selector":"tags"}

NameRequiredDescriptionDefault
pathYesPath to the JSON, YAML, or TOML file.
selectorYesDot-notation selector path to an array.
predicateYesPredicate in "field=value" format to match elements for deletion.
agent_presetNoWhen true, replace uses the agent preset: unique, require_change, fuzzy floor 0.90, allow_absent_old false. Off unless set.
expected_sha256NoSHA-256 hex of the file's current bytes. If it does not match, the tool returns error_kind stale and writes nothing.

TDQS

A4.3/5.0
Behavior4/5

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

Annotations already declare destructiveHint=true and readOnlyHint=false, so the base safety profile is covered. The description adds genuinely new behavior: changed/removed result counts, 0 when nothing matches, and exit 0 / ok idempotency — useful for a mutating tool with no output schema. It does not cover permissions or the stale/expected_sha256 failure path beyond the schema.

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?

Front-loaded with the action and predicate mechanism, then progressively adds per-case syntax and an example with no filler sentences. Some parsing cost comes from the compressed '(CLI) or the predicate field (plans)' parenthetical and stacked clauses, but nothing is wasted.

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?

With 5 parameters, no output schema, and mutation semantics, the description supplies the return-field summary (changed/removed) and idempotency guarantee that would otherwise be missing. Remaining gaps — ordering of deletions, error surface other than stale, and the agent_preset interaction — are minor for correct invocation.

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

Parameters4/5

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

Schema coverage is already 100%, so baseline is 3, but the description goes beyond the schema by spelling out multiple predicate dialects (=x, _=x, value=x, field=value), nested-path predicates, and a full worked JSON example mapping predicate/path/selector. That is real added semantic value for the most error-prone 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?

States a specific verb and resource with mechanism: delete array elements matching a key=value predicate, and explicitly contrasts with doc.update's inside-the-path filtering. An agent can distinguish this from the large sibling set (doc_delete, doc_update, ast_delete_symbol) without opening a schema.

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 concrete selection guidance per case (scalar arrays use .=x/_=x/value=x; object arrays use role=admin; nested paths use settings.theme=dark) and names doc.update as the alternative with the differentiator. It stops short of a full when-not-this-tool rule, but the routing information is clear.

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

doc_diffB
Read-only

Compare two structured files (JSON, YAML, or TOML) and show differences. Example: {"file_a": "old.json", "file_b": "new.json"}

NameRequiredDescriptionDefault
file_aYesFirst file path (relative to working directory).
file_bYesSecond file path (relative to working directory).

TDQS

B3.2/5.0
Behavior3/5

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

Annotations already declare readOnlyHint=true and openWorldHint=false, so safety is covered by structured data. The description usefully adds the supported input formats, but says nothing about output shape (unified diff vs. structured summary), depth of comparison, or behavior on missing/unparsable files, which matters given there is no output schema.

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?

Two short sentences, front-loaded with the core action followed by a concrete example. Nothing is padded, though the inline JSON example is slightly inelegant inside prose.

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

Completeness3/5

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

For a diff tool with no output schema and no annotations on comparison semantics, the description should say what the differences output looks like and how errors are surfaced. Format support is covered, but return-shape disclosure is absent.

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% and both parameters are documented as file paths relative to the working directory, so the schema does the heavy lifting. The description's example duplicates that meaning and adds only the file-format scope, which is a marginal gain.

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

Purpose4/5

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

States a specific verb and resource ('Compare two structured files ... and show differences') and scopes the supported formats to JSON, YAML, or TOML, which implicitly separates it from sibling ast_diff. It never names an alternative sibling explicitly, so the differentiation is inferred rather than stated.

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

Usage Guidelines2/5

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

There is no when-to-use guidance, no exclusions, and no pointer to alternatives such as ast_diff for source-code comparisons. The included example illustrates argument shape rather than usage context.

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

doc_ensureA
Destructive

Set a value only if the selector path does not already exist. Example: {"value":30,"path":"config.json","selector":"timeout"}

NameRequiredDescriptionDefault
pathYesPath to the JSON, YAML, or TOML file.
valueYesValue to set only if the key does not already exist.
selectorYesDot-notation selector path.
agent_presetNoWhen true, replace uses the agent preset: unique, require_change, fuzzy floor 0.90, allow_absent_old false. Off unless set.
expected_sha256NoSHA-256 hex of the file's current bytes. If it does not match, the tool returns error_kind stale and writes nothing.

TDQS

A3.6/5.0
Behavior3/5

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

Annotations already declare destructiveHint=true and readOnlyHint=false, so the safety profile is covered structurally. The description adds the useful conditional-write rule, but says nothing about the expected_sha256 stale handling, error behavior, or the agent_preset replace mode that the schema mentions, so the added behavioral value is modest.

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 sentences, front-loaded with the conditional rule and immediately followed by a compact, high-signal example. No filler and nothing redundant.

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 five-parameter mutation tool with fully-covered schema and existing annotations, the description covers the essential contract (conditional set). It omits any mention of the stale-hash guard or the agent_preset behavior, but those are documented in the schema, so the gap is minor.

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 all five parameters are already documented, including path, picker, value and the stale/preset flags. The inline example adds a concrete illustration of the selector/path/value shape but no semantics beyond the schema, so baseline 3 applies.

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

Purpose4/5

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

The description states a specific operation with condition: set a value only if the selector path does not already exist. That conditional-write semantics is clear enough to distinguish it from an unconditional sibling like doc_set, though no sibling is named explicitly.

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?

It communicates the key usage condition (only write when the key is absent), which implies when to prefer this over doc_set, but it never names an alternative or an explicit when-not case. Guidance is inferred rather than stated.

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

doc_getA
Read-only

Read a value from a JSON, YAML, or TOML file by selector path. Example: {"path": "package.json", "selector": "version"}

NameRequiredDescriptionDefault
pathYesFile path (relative to working directory).
selectorYesDot-notation selector path for the value to read (e.g., "version", "db.pool"). Alias `key` accepted so agents that emit the LLM-prior field name still work.

TDQS

A3.5/5.0
Behavior3/5

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

Annotations already declare readOnlyHint=true and openWorldHint=false, so the safety profile is covered. The description usefully adds that three file formats and dot-notation selectors are supported, but it says nothing about the non-happy paths — missing key, malformed file, unsupported extension — or about what value shape comes back.

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 sentences, front-loaded with the capability and followed by a concrete example. No filler, no restatement of the tool name, and every clause adds information.

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

Completeness3/5

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

There is no output schema, so the description carries the burden of explaining the return value, and it does not describe the returned value's type, nesting, or error behavior for an unmatched selector. Given the simplicity of a two-parameter read it is adequate, but not complete for an agent that must handle misses.

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 both parameters are already documented, including the `key` alias and a sample selector. The description's example ({"path": "package.json", "selector": "version"}) restates rather than extends the schema, so the baseline 3 applies.

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

Purpose4/5

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

The description states a specific verb+resource+mechanism: 'Read a value from a JSON, YAML, or TOML file by selector path.' The supported formats and the selector mechanism distinguish it from read_file (whole-file reads) and from mutation siblings like doc_set/doc_append/doc_delete. It stops short of naming a sibling, so an agent must infer the boundary with doc_query on its own.

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?

Usage is implied by the mechanism (use when you need one value from a structured data file, addressed by dot-notation path), but there is no explicit when-to-use statement, no when-not, and no named alternative such as doc_query or read_file. The inline example shows the calling shape rather than the selection criteria.

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

doc_mergeB
Destructive

Deep-merge a JSON object into a document root, or into a selector path (e.g. multi-doc YAML 0 / [0]). Example: {"value":{"database":{"host":"localhost","port":5432}},"path":"config.yaml"}

NameRequiredDescriptionDefault
pathYesPath to the JSON, YAML, or TOML file.
valueYesObject to deep-merge into the file (or selected object).
selectorNoOptional selector for the merge target (e.g. `0` for multi-doc YAML). When omitted, merges into the document root.
agent_presetNoWhen true, replace uses the agent preset: unique, require_change, fuzzy floor 0.90, allow_absent_old false. Off unless set.
expected_sha256NoSHA-256 hex of the file's current bytes. If it does not match, the tool returns error_kind stale and writes nothing.

TDQS

B3.2/5.0
Behavior3/5

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

Annotations already declare destructiveHint=true and readOnlyHint=false, so the write/destructive profile is covered. The description usefully adds merge semantics (partial update rather than replace) and the selector-target concept, but says nothing about error/failure behavior, staleness handling, or what happens to existing keys not mentioned in the value.

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?

Two tight sentences with the core semantics front-loaded and an inline example that earns its place by showing the path/value shape. No 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 write tool whose safety profile is carried by annotations and whose parameters are fully documented in the schema, the description supplies the essential distinguishing concept (deep-merge into root or selector). Only the missing routing against sibling doc_* tools keeps it from being fully complete.

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 five parameters. The description's example reinforces path/value usage and it echoes the selector concept, but it adds no format or syntax detail beyond what the schema provides. Baseline 3 is appropriate.

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

Purpose4/5

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

States a specific verb (deep-merge) and resource (a JSON object into a document root or selector path), which is more precise than a generic 'update'. However, it does not differentiate from close siblings like doc_set, doc_update, or doc_ensure, which an agent would need to disambiguate among.

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

Usage Guidelines2/5

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

The example shows how to call it but gives no when-to-use guidance, no when-not-to-use, and names no alternatives among the many doc_* siblings. The agent must infer that 'merge' rather than 'set' is the selection criterion.

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

doc_moveB
Destructive

Move a value from one selector path to another within the same file. Example: {"to":"new_key","path":"config.json","from":"old_key"}

NameRequiredDescriptionDefault
toYesDot-notation destination path.
fromYesDot-notation source path.
pathYesPath to the JSON, YAML, or TOML file.
agent_presetNoWhen true, replace uses the agent preset: unique, require_change, fuzzy floor 0.90, allow_absent_old false. Off unless set.
expected_sha256NoSHA-256 hex of the file's current bytes. If it does not match, the tool returns error_kind stale and writes nothing.

TDQS

B3.4/5.0
Behavior3/5

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

Annotations already declare destructiveHint=true and readOnlyHint=false, so the safety profile is covered. The description adds the same-file constraint but does not disclose the destructive behavior an agent most needs here — whether an existing destination value is overwritten, whether a missing 'from' errors, or whether the move is atomic. With annotations doing the heavy lifting, this is a moderate 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?

Two sentences, zero padding, with the core operation front-loaded and the example immediately following to disambiguate the argument roles.

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 three-required-parameter mutation tool with full schema coverage, annotations, and no output schema, the description is largely sufficient. The main omission is conflict semantics on the destination path, which matters given the destructive hint.

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 all five parameters including agent_preset and expected_sha256 are already documented. The example demonstrates how path/from/to combine, which is mildly useful, but no syntax or format meaning is added beyond the schema.

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

Purpose4/5

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

States a specific verb and resource (move a value from one selector path to another) and scopes it with 'within the same file,' which usefully separates it from move_file and ast_move. The inline example makes the operation concrete. It stops short of explicitly naming which sibling to prefer for cross-file or AST moves.

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

Usage Guidelines2/5

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

The example illustrates a call but gives no when-to-use guidance, no prerequisites, and no comparison against alternatives like ast_move, move_file, or doc_set. An agent must infer from the name alone when this is the right tool.

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

doc_prependB
Destructive

Prepend a value to the beginning of an array at a selector path.

NameRequiredDescriptionDefault
pathYesPath to the JSON, YAML, or TOML file.
valueYesValue to prepend to the array.
selectorYesDot-notation selector path to an array.
agent_presetNoWhen true, replace uses the agent preset: unique, require_change, fuzzy floor 0.90, allow_absent_old false. Off unless set.
expected_sha256NoSHA-256 hex of the file's current bytes. If it does not match, the tool returns error_kind stale and writes nothing.

TDQS

B3.1/5.0
Behavior2/5

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

Annotations already declare readOnlyHint=false and destructiveHint=true, so the mutation/safety profile is covered by structured data. The description adds nothing beyond that – no mention of write atomicity, the stale/expected_sha256 guard behavior, or what happens when the selector does not resolve to an array.

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?

A single front-loaded sentence with no wasted words; the action and target are stated immediately.

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

Completeness3/5

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

For a destructive mutation tool with no output schema, the description covers the core action and the schema covers all parameters, but it omits behavioral outcomes such as error handling on a stale file or non-array selector, leaving gaps an agent would want filled.

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

Parameters3/5

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

Schema description coverage is 100%, so the baseline is 3. The description restates 'array at a selector path' without adding syntax, type, or constraint detail beyond what the schema already documents for path, selector, and value.

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

Purpose4/5

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

The description names a specific verb (prepend) and resource (a value into an array at a selector path), so an agent can tell it apart from doc_append conceptually. It does not, however, explicitly differentiate itself from the many sibling tools that also mutate documents (doc_set, doc_update, doc_append).

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

Usage Guidelines2/5

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

There is no guidance on when to choose this tool over doc_append, doc_set, or doc_update, nor any stated prerequisites or exclusions. The usage is only implied by the verb 'prepend'.

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

doc_queryA
Read-only

Query a JSON, YAML, or TOML file. Actions: "has" (exists, true/false), "keys" (keys of one object; omit selector for .; e.g. database or items[0]), "len" (length of one object or array; omit selector for .; e.g. items or database), "select" (filter via selector predicates, e.g. users[role=admin]; no separate predicate field), "flatten" (leaf paths). keys need one object; len needs one object or array; items[*] is fail-closed ambiguous (use items[0] / items[1]). Example: {"action": "has", "path": "config.json", "selector": "database.host"}

NameRequiredDescriptionDefault
pathYesFile path (relative to working directory).
actionYesQuery action: "has" (check existence), "keys" (list keys), "len" (count), "select" (filter array), or "flatten" (list all paths).
selectorNoSelector path. Required for has/select. Optional for keys/len (defaults to `.`). Ignored for flatten. keys need one object (`database`, `items[0]`); len needs one object or array (`database`, `items`); multi-match (`items[*]`) is fail-closed `ambiguous` (use `items[0]` / `items[1]`). Alias `key` accepted because agents often emit that name (LLM prior).

TDQS

A3.9/5.0
Behavior4/5

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

Instead of just relying on the readOnlyHint/openWorldHint annotations, the description adds behavioral detail: fail-closed 'ambiguous' results for items[*], the requirement that select uses inline predicates rather than a separate predicate field, and the per-action preconditions. It does not describe return format, but the annotations already establish the read-only, non-open-world safety profile.

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 purpose, then lists actions and their constraints, ending with a worked example. It is dense to the point of being run-on, but every sentence serves a purpose and there is no 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 2-required-param read-only query tool with no output schema and full schema coverage, the description covers all actions, selector semantics, the ambiguity failure mode, and an invocation example. It is complete enough to call correctly; only the exact return shape is unstated, which is minor given the action names imply it.

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

Parameters3/5

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

Schema coverage is 100%, so the schema already documents all three parameters, including the selector alias 'key' and which actions require or default selector. The description repeats and reinforces the same semantics with examples rather than adding new meaning beyond 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 opens with a specific verb+resource ('Query a JSON, YAML, or TOML file') and enumerates all five query actions with concrete behavior. An agent can distinguish it from read_file, doc_get, and other siblings because it is explicitly a structured-data query tool with has/keys/len/select/flatten.

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 gives usage constraints per action (e.g., keys need one object, len needs one object or array, items[*] is fail-closed ambiguous, use items[0]/items[1]) which shape how to invoke. It does not, however, state when to choose doc_query over read_file, search_files, or doc_get, so explicit sibling routing is absent.

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

doc_setA
Destructive

Set a value at a single concrete selector path in a JSON, JSONC, YAML, TOML, .env, .ini, or .properties file (keys and indexes such as server.port or items.0.v). Parser-backed; output is always valid. Not for predicates or wildcards (items[name=foo].v, items[].v); use doc.update for multi-match writes. Default creates a missing key and fails with not_found if the file is missing. Set if_exists=true to soft-skip when the file is missing or the selector is not present (does not create the key). Single concrete path only (keys/indexes). For selector predicates or wildcards (items[name=foo].v, items[].v) use doc_update / plan doc.update. Set if_exists=true to soft-skip a missing file or missing selector (does not create the key). Example: {"value":"2.0.0","path":"package.json","selector":"version"}

NameRequiredDescriptionDefault
pathYesPath to the JSON, YAML, or TOML file.
valueYesValue to set (any JSON type).
strictNoEnable strict mode (default true). When true, roll back all file writes if format or validate lifecycle steps fail.
selectorYesDot-notation selector path (e.g. "server.port", "env.0.value"). `.` (or empty / `/`) is the document root and replaces the whole value. Alias `key` accepted because agents often emit that name (LLM prior).
if_existsNoSoft-skip (no write) when the file is missing or the selector is not present. Default false: missing file is `not_found`; a missing selector creates the key.
agent_presetNoWhen true, replace uses the agent preset: unique, require_change, fuzzy floor 0.90, allow_absent_old false. Off unless set.
expected_sha256NoSHA-256 hex of the file's current bytes. If it does not match, the tool returns error_kind stale and writes nothing.

TDQS

A4/5.0
Behavior4/5

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

Annotations already declare destructiveHint=true and readOnlyHint=false, so the safety profile is known; the description adds substantive context beyond that: parser-backed writes that always produce valid output, default key creation, not_found on missing files, and the if_exists soft-skip semantics. It does not disclose concurrency/rate considerations, so it stops short of a 5.

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

Conciseness3/5

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

Front-loaded with the core action and formats, but visibly redundant: the wildcard/predicate exclusion appears twice and the if_exists soft-skip explanation is repeated nearly verbatim. Trimming those duplicates would improve it without losing information.

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 7-parameter mutation tool with annotations and no output schema, the description covers the essential semantics: valid-output guarantee, missing-file/key behavior, and the alternative for wildcard writes. It leaves out only edge concerns like rollback interaction (left to the strict schema field) and the SHA-256 staleness guard.

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

Parameters3/5

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

Schema description coverage is 100%, so the schema already documents path, selector, value, strict, if_exists, agent_preset, and expected_sha256. The description restates if_exists and selector format and adds one concrete example, but mostly duplicates the schema rather than adding new meaning, so baseline 3 applies.

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

Purpose5/5

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

States a specific verb and resource: set a value at a single concrete selector path across enumerated file formats. It also distinguishes itself from siblings by naming doc_update for multi-match writes. An agent can identify the tool's scope without opening the schema.

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

Usage Guidelines4/5

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

Explicitly gives when-not-to-use (predicates/wildcards -> doc_update) plus default vs if_exists behavior for missing files/keys, which is genuine routing guidance. However, it references the alternative inconsistently as both 'doc.update' and 'doc_update / plan doc.update', which muddies the handoff slightly.

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

doc_updateA
Destructive

Set a new value at every location matching a selector. Use wildcards (items[].enabled) or selector predicates (items[name=foo].v). Not a separate --where flag; the filter is part of the selector string. Multi-match writes: use selector predicates or wildcards (items[name=foo].v, items[].enabled). Prefer this over doc_set when filtering by field. Example: {"value":7,"path":"config.toml","selector":"items[name=a].v"}

NameRequiredDescriptionDefault
pathYesPath to the JSON, YAML, or TOML file.
valueYesNew value for all matching locations.
selectorYesDot-notation selector path (supports wildcards and predicates).
agent_presetNoWhen true, replace uses the agent preset: unique, require_change, fuzzy floor 0.90, allow_absent_old false. Off unless set.
expected_sha256NoSHA-256 hex of the file's current bytes. If it does not match, the tool returns error_kind stale and writes nothing.

TDQS

A4.2/5.0
Behavior4/5

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

Annotations already declare destructiveHint=true and readOnlyHint=false; the description adds the crucial multi-match/multi-write semantic ("Multi-match writes") that explains what the destructive behavior actually does. It does not cover the expected_sha256/stale-failure path, but that is documented in the schema.

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

Conciseness3/5

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

Front-loaded and includes a useful example, but the wildcard/predicate guidance is stated twice ("Use wildcards (items[*].enabled) or selector predicates (items[name=foo].v)" reappears as "Multi-match writes: use selector predicates or wildcards..."), which is redundant 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 5-param mutation with no output schema, the description covers purpose, selector syntax, sibling choice, and an example, which is enough to invoke correctly. It omits mention of agent_preset and the stale-guard behavior, though both are covered in the schema.

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, but the description goes beyond the schema by clarifying that the filter is part of the selector string ("Not a separate --where flag") and by supplying concrete selector examples. It adds real meaning over the terse schema field 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?

States a specific verb and resource ("Set a new value at every location matching a selector") and immediately names the sibling it competes with ("Prefer this over doc_set when filtering by field"). An agent can distinguish it from doc_set and doc_delete_where without opening a schema.

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 explicit usage context: use selectors/wildcards for multi-match writes and prefer this over doc_set when filtering by field. It stops short of when-not guidance (e.g., when to fall back to doc_set or how it relates to doc_delete_where), so not a full 5.

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

execute_planA
Destructive

Execute a multi-step transaction plan atomically (MCP equivalent of patchloom tx). Provide an inline plan object or a plan_path. plan requires version and operations (alias ops). Each operation requires string op. Other plan and op fields are allowed. Call operation_schema with the op name for that operation's fields. Optional plan.cwd must be a relative path under the server workspace. Absolute plan.cwd and ../ escapes are rejected. Do not set both plan.cwd and for_each. plan.format/validate are ignored on MCP. Example: {"plan": {"version": 1, "operations": [{"op": "doc.set", "path": "app.yaml", "selector": "name", "value": "x"}]}}

NameRequiredDescriptionDefault
planNoInline plan object. Field details for one op come from `operation_schema`. `operations` may be sent as `ops`.
strictNoOptional override of the plan's `strict` field. Applied only when present so `{"plan":{"strict":false}}` is not overwritten. MCP still strips plan.format/validate (lifecycle shells are not run from submitted plans).
plan_pathNoPath (relative to cwd) to a plan file (JSON, YAML, or TOML). Used only if `plan` is not provided.
agent_presetNoWhen true, replace ops in this plan use the agent preset (#2614).

TDQS

A4.3/5.0
Behavior4/5

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

Annotations declare destructiveHint=true, and the description adds concrete behavioral contracts: atomicity, cwd sandboxing rules (relative-only, no ../ escapes), that plan.format/validate are ignored on MCP, and the for_each conflict. These go well beyond the annotation's binary flags. Does not state rollback semantics on partial failure beyond 'atomically'.

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?

Front-loads the purpose, then constraints, then a worked example. Dense but every clause carries a real constraint. Borderline long, but the sandboxing rules and alias notes justify the length.

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?

No output schema, so the agent has no structured return contract; the description covers inputs and semantics well and even provides an example plan. Missing only return/status reporting and failure handling for an inherently destructive, atomic operation.

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 already 100% with useful per-param descriptions. The description still adds value: the op/ops alias, that arbitrary extra fields are allowed, that plan.cwd must be relative under the workspace, and it redirects to operation_schema for op field details. Slightly exceeds the baseline-3 expectation.

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

Purpose5/5

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

States a specific verb and resource ('Execute a multi-step transaction plan atomically') and explains the MCP-to-CLI equivalence ('MCP equivalent of patchloom tx'). An agent can immediately distinguish this from atomic individual-op siblings like apply_patch or doc_set.

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 operational context (inline plan or plan_path, use operation_schema to look up op fields) and rules ('Do not set both plan.cwd and for_each'). Lacks an explicit statement of when to prefer this over looping individual atomic tools, though the atomicity framing implies it.

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

explain_planB
Read-only

Explain a tx plan in structured JSON (same as CLI patchloom explain --json). Provide inline plan text (plan) or a plan file (path). Format hint optional (json/yaml/toml). Read-only: does not execute the plan. Example: {"plan": "{"version": 1, "operations": [{"op": "file.create", "path": "a.txt", "content": "x"}]}"}

NameRequiredDescriptionDefault
pathNoPath to a plan file (relative to working directory).
planNoInline plan text (JSON, YAML, or TOML). Same document as CLI `explain`.
formatNoFormat hint: json, yaml, or toml (auto-detected from path extension).

TDQS

B3.4/5.0
Behavior3/5

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

Annotations already declare readOnlyHint=true and openWorldHint=false, so the read-only nature is covered. The description reinforces this and adds that output is structured JSON matching the CLI, but adds little beyond what annotations and the CLI reference imply.

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?

Front-loads the purpose, then parameter guidance, then the read-only guarantee, ending with a concrete example. Efficient overall, though the embedded example adds some length without new information beyond the schema.

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

Completeness3/5

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

With no output schema, the description carries the burden of describing return values, and it only says 'structured JSON' with a CLI reference rather than detailing the returned structure. Adequate for invocation but thin on what the agent will receive.

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 both the plan/path alternatives and the format hint are already documented in the schema. The description restates these (inline plan vs plan file, json/yaml/toml) without adding syntax or precedence rules beyond the schema.

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

Purpose4/5

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

States a specific verb (explain) and resource (tx plan) and clarifies that it returns structured JSON without executing the plan. This implicitly distinguishes it from the sibling execute_plan, though it never names that sibling.

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?

By stating 'does not execute the plan', the description implies this is for previewing/understanding rather than running a plan, which is useful context. However, it never explicitly names execute_plan as the alternative or states when-not to use this tool.

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

fix_whitespaceA
Destructive

Normalize whitespace in a file or directory. A directory path expands with the same ignore-aware walker as CLI tidy fix (one write per text file). When op fields are omitted, defaults match CLI tidy fix (trim trailing whitespace + ensure final newline; mixed line endings flatten to the dominant style; uniform CRLF/LF stays). Set normalize_eol to keep to opt out of flattening. Precedence: defaults → plan write_policy → op fields. Plan write_policy is not re-applied at commit for paths last written by tidy.fix so op fields stick (#1840, #1847). Defaults: trim trailing whitespace and ensure final newline when those fields are omitted. Example: {"trim_trailing_whitespace":true,"path":"src/main.rs","ensure_final_newline":true}

NameRequiredDescriptionDefault
pathYes
linesNoLine range restriction for dedent/indent: "10:50" (1-based inclusive).
dedentNoDedent specification: "4", "tab", or "auto".
indentNoIndent specification: "4", "tab".
agent_presetNoWhen true, replace uses the agent preset: unique, require_change, fuzzy floor 0.90, allow_absent_old false. Off unless set.
normalize_eolNo
collapse_blanksNoCollapse consecutive blank lines into a single blank line.
expected_sha256NoSHA-256 hex of the file's current bytes. If it does not match, the tool returns error_kind stale and writes nothing.
ensure_final_newlineNo
trim_trailing_whitespaceNo

TDQS

A4.2/5.0
Behavior4/5

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

Annotations already declare destructiveHint=true and readOnlyHint=false, but the description adds real behavioral context: one write per text file, EOL flattening to the dominant style, opt-out via normalize_eol, and the subtle commit-time write_policy interaction (#1840, #1847). It stops short of describing staleness/error behavior beyond the schema's expected_sha256 note.

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?

Front-loaded with purpose and scope, then defaults and precedence. Dense but every sentence carries behavioral weight; the embedded example and issue references add slight bulk but are justified.

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 10-param mutation tool with no output schema, the description covers scope, defaulting, precedence, EOL handling, and the write_policy edge case. Nothing critical to invoking it correctly is missing.

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

Parameters3/5

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

Schema coverage is 60%, so the schema documents several params but not all. The description usefully explains defaults for trim_trailing_whitespace, ensure_final_newline, and normalize_eol, plus the override precedence, but leaves lines, dedent, indent, agent_preset, collapse_blanks, and expected_sha256 largely to the schema. Baseline 3 fits given partial coverage.

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

Purpose5/5

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

States a specific verb+resource ('Normalize whitespace in a file or directory') and clarifies scope (directory expands with the same ignore-aware walker as CLI tidy fix, one write per text file). An agent can immediately distinguish this mutation tool from the read-only sibling tidy_check.

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?

Explains when fields apply and how defaults behave, plus the precedence chain (defaults → plan write_policy → op fields). However it never explicitly names tidy_check or batch_tidy as alternatives or states when NOT to use this tool, so routing guidance is implied rather than explicit.

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

git_statusA
Read-only

Show uncommitted file changes vs git HEAD. Returns lists of modified, created, and deleted files. Omits .patchloom/ backup paths from --apply undo sessions. No parameters required.

NameRequiredDescriptionDefault

No parameters

TDQS

A3.9/5.0
Behavior4/5

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

Annotations already declare readOnlyHint=true and openWorldHint=false, so safety is covered. The description still adds real value by disclosing the return shape (modified/created/deleted lists) and a non-obvious filtering behavior (.patchloom/ paths excluded from --apply undo sessions), which the agent could not infer otherwise.

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?

Four short sentences, each load-bearing: purpose first, then return contents, then the filtering caveat, then the parameter note. No filler or redundancy.

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?

With no output schema, the description carries the burden of describing results and does so adequately. It is nearly complete for a zero-parameter read tool; the only minor omission is any statement about untracked/ignored file handling beyond the .patchloom note.

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 zero parameters, so the baseline is 4; the explicit 'No parameters required.' correctly confirms this rather than leaving the agent to guess. Nothing further is needed for an empty schema with 100% coverage.

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

Purpose4/5

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

States a specific verb and resource: 'Show uncommitted file changes vs git HEAD.' An agent immediately knows this is a read of working-tree state. It does not, however, explicitly differentiate itself from adjacent status/diff siblings such as undo_list or doc_diff.

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?

Usage is implied by the scope note ('Omits .patchloom/ backup paths from --apply undo sessions'), which hints at the undo workflow context. But there is no explicit when-to-use / when-not-to-use guidance and no named alternative among the many diff/undo siblings.

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

list_filesA
Read-only

List files under the workspace (or given roots) with the same ignore/exclude/glob rules as search. Use this instead of a generic filesystem MCP list_dir/tree. Caps results (default max_results=500) and reports truncated+total_matched when capped. max_depth prunes the walk at each root (does not enter deeper dirs). max_results still counts all in-depth matches then truncates (total_matched remains honest). Prefer relative paths. Example: {"path": "src/", "exclude_patterns": ["target/**"], "max_results": 100, "max_depth": 3}

NameRequiredDescriptionDefault
pathNoSingle walk root (LLM prior). Equivalent to `paths: [path]` when `paths` is empty. If both are set, `paths` wins.
globsNoGlob include patterns (same role as search `globs` / CLI `--glob`).
pathsNoWalk roots relative to working directory (defaults to workspace root). Prefer this for multi-root lists.
max_depthNoMax path depth under each root (1 = only files directly under the root). Applied during the walk: deeper directories are not entered (#2078). Omit for unlimited depth (still subject to max_results).
max_resultsNoMax paths to return. Default 500 when omitted or 0 (agent context budget).
include_hiddenNoInclude hidden files (still never walks `.git` / `.patchloom`).
exclude_patternsNoExclude glob patterns (in addition to ignore files).
custom_ignore_filenamesNoCustom ignore filenames (e.g. `.agentignore`).

TDQS

A4.1/5.0
Behavior4/5

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

Annotations only declare readOnlyHint and openWorldHint, so the description adds substantial behavioral context beyond them: result capping (default max_results=500), truncated+total_matched reporting, and the nuance that max_depth prunes the walk while max_results counts all in-depth matches before truncating. It does not describe return shape, but no output schema exists and the truncated/total_matched signal is disclosed.

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?

Front-loaded with the primary purpose and the substitution guidance, then detail on capping and depth. Slightly dense and mixes several concepts (routing, caps, depth, path preference, example) but no sentence is wasted.

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

Completeness4/5

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

For an 8-param read-only listing tool with full schema coverage and annotations, the description covers the key runtime behaviors an agent needs: default cap, truncation signal, depth pruning, and path preference. Missing only explicit return-format detail, which is largely implied by truncated/total_matched.

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

Parameters3/5

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

Schema coverage is 100%, so the schema already documents all 8 parameters, including defaults, precedence rules, and depth semantics. The description restates max_results, max_depth, and exclude_patterns behavior and adds an example, which is helpful but largely duplicative of the schema. Baseline 3 applies.

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

Purpose5/5

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

States a specific verb+resource ('List files under the workspace or given roots') and immediately differentiates from siblings by naming search semantics and explicitly telling the agent to use this 'instead of a generic filesystem MCP list_dir/tree.' The sibling list contains search_files, so the cross-reference is meaningful.

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 routing guidance ('Use this instead of a generic filesystem MCP list_dir/tree') and a concrete example call. It does not contrast against the actual sibling search_files, which is the closest in-family alternative, so routing is clear but not fully exhaustive.

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

md_dedupe_headingsC
Destructive

Remove later whole sections whose heading text+level already appeared (heading and body until next same-or-higher heading; unique second-section content is discarded). Removes later whole sections with the same heading level+text (body under the second heading is discarded, not merged).

NameRequiredDescriptionDefault
pathYes
agent_presetNoWhen true, replace uses the agent preset: unique, require_change, fuzzy floor 0.90, allow_absent_old false. Off unless set.
expected_sha256NoSHA-256 hex of the file's current bytes. If it does not match, the tool returns error_kind stale and writes nothing.

TDQS

C2.9/5.0
Behavior4/5

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

Annotations already declare destructiveHint=true, so the safety profile is known, but the description goes further and specifies what is destroyed: the entire second section body is discarded, not merged, and unique second-section content is explicitly lost. That is meaningful context an annotation cannot convey. It still omits irreversibility/undo and idempotency behavior.

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

Conciseness2/5

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

Two sentences state the same rule twice — 'removes later whole sections with the same heading level+text' restates sentence one almost verbatim. Roughly half the text is redundant, which is under-editing rather than concision.

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

Completeness2/5

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

For a destructive markdown mutation with no output schema, the description should cover outcome/reversibility and the expected_sha256 stale-write path; it covers neither. The core removal semantics are present, but an agent still lacks enough to call this safely and correctly.

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

Parameters2/5

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

Schema coverage is a middling 67%, and the description contributes no parameter meaning at all. The required 'path' parameter carries no description in either the schema or the description, and neither agent_preset nor expected_sha256 (stale-write guard) is referenced, even though the latter bears directly on failed invocations.

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

Purpose4/5

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

The verb 'Remove' targets a specific resource: later whole sections whose heading text+level already appeared. The parenthetical defines the section boundary ('until next same-or-higher heading'), so an agent knows exactly what gets removed. However, it never names or contrasts with nearby siblings like md_move_section, md_replace_section, or doc_merge, so differentiation is left to inference.

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

Usage Guidelines2/5

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

No when-to-use guidance, no prerequisites, no mention of alternatives. Given the crowded markdown-section sibling set (md_replace_section, md_move_section, doc_merge), the absence of routing guidance is a real gap.

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

md_insert_after_headingB
Destructive

Insert content immediately after a markdown heading line (before any existing body). For a sibling section after the full body, use md.insert_after_section. Inserts immediately under the heading line (before existing body). For a sibling ## section after the full body, use md_insert_after_section.

NameRequiredDescriptionDefault
pathYes
contentYes
headingYes
agent_presetNoWhen true, replace uses the agent preset: unique, require_change, fuzzy floor 0.90, allow_absent_old false. Off unless set.
expected_sha256NoSHA-256 hex of the file's current bytes. If it does not match, the tool returns error_kind stale and writes nothing.

TDQS

B3.3/5.0
Behavior2/5

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

Annotations declare destructiveHint=true, readOnlyHint=false, signaling a mutating operation. The description says nothing about failure modes, whether existing content is preserved/reordered, or how heading matching works. The expected_sha256 stale-check behavior is described only in the schema, not here. With a destructive mutation and no annotations covering what gets destroyed, the description should do more.

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

Conciseness2/5

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

The description repeats itself nearly verbatim: 'Insert content immediately after a markdown heading line (before any existing body)' then again 'Inserts immediately under the heading line (before existing body)', and the md_insert_after_section guidance is stated twice. Three of five sentences are redundant, which is under-edited rather than concise.

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

Completeness2/5

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

A destructive mutation tool with no output schema and 40% schema coverage should explain failure modes, heading-match rules, and how existing body content is affected. Only insert-point placement is covered; the stale-check, agent_preset behavior, and heading-matching semantics are left entirely to structured fields.

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 40%, so three of five parameters (path, heading, content) are undocumented in the schema. The description explains where content lands relative to heading, partially compensating for 'heading' and 'content' semantics, but adds nothing on path or the heading-matching algorithm (exact? case-sensitive?). Baseline 3 given the middling coverage and partial compensation.

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

Purpose5/5

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

States a specific verb (insert) and target (immediately after a markdown heading line, before existing body), and explicitly names the sibling md_insert_after_section to differentiate its scope. An agent can distinguish this from md_insert_before_heading and md_insert_after_section without opening schemas.

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

Usage Guidelines4/5

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

Explicitly names the alternative (md_insert_after_section) and the condition that selects it ('after the full body'). However, it doesn't address when to use this vs md_insert_before_heading, which is the closest sibling by name. Clear context but not a full routing set.

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

md_insert_after_sectionB
Destructive

Insert content after the full section body (sibling placement). Use when adding a new ## section after this section's content. Prefer md.insert_after_heading for content under the heading line. Inserts after the full section body (sibling placement). Prefer md_insert_after_heading for content under the heading. Example: {"content":"## FAQ\n\nCommon questions.\n","path":"README.md","heading":"## Config"}

NameRequiredDescriptionDefault
pathYes
contentYes
headingYes
agent_presetNoWhen true, replace uses the agent preset: unique, require_change, fuzzy floor 0.90, allow_absent_old false. Off unless set.
expected_sha256NoSHA-256 hex of the file's current bytes. If it does not match, the tool returns error_kind stale and writes nothing.

TDQS

B3.4/5.0
Behavior3/5

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

Annotations already declare destructiveHint=true, readOnlyHint=false and openWorldHint=false, so the safety profile is covered. The description adds placement semantics (sibling vs. under-heading), which is useful, but says nothing about the mutation being applied to a live file, whether it is idempotent, or how expected_sha256/stale errors change behavior beyond what the schema states.

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

Conciseness2/5

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

The core sentence 'Insert content after the full section body (sibling placement)' appears twice and the routing advice to md_insert_after_heading appears twice in slightly different forms. Roughly half the text is redundant, so the definition is not front-loaded efficiently.

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

Completeness3/5

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

There is no output schema, and for a destructive write tool the description does supply placement semantics plus a concrete example, which is adequate. It still omits anything about failure modes, atomicity, or what the tool returns on success, leaving gaps against the mutation complexity.

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 only 40%: path, content and heading carry no schema descriptions, and only agent_preset and expected_sha256 are documented. The worked example does demonstrate how path, heading and content combine, which partially compensates, but it is thin for a five-parameter mutation tool.

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

Purpose4/5

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

The description states a specific verb and resource (insert content after a full section body) and explicitly distinguishes itself from the sibling md_insert_after_heading. However, the purpose is stated twice in near-identical wording, which muddies rather than sharpens the message.

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?

It gives an explicit when-to-use condition ('adding a new ## section after this section's content') and names the alternative plus the condition that selects it ('Prefer md.insert_after_heading for content under the heading line'). The only flaw is that the alternative is referenced twice and the dotted name doesn't exactly match the sibling tool name.

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

md_insert_before_headingC
Destructive

Insert content immediately before a markdown heading line.

NameRequiredDescriptionDefault
pathYes
contentYes
headingYes
agent_presetNoWhen true, replace uses the agent preset: unique, require_change, fuzzy floor 0.90, allow_absent_old false. Off unless set.
expected_sha256NoSHA-256 hex of the file's current bytes. If it does not match, the tool returns error_kind stale and writes nothing.

TDQS

C2.7/5.0
Behavior2/5

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

Annotations declare destructiveHint=true and non-readonly, so the agent knows this mutates. The description adds nothing beyond that: it doesn't explain that an existing heading line is required (behavior if heading absent), how expected_sha256 staleness handling works, or that content is written to the file, all of which matter for a destructive write with 60% undocumented parameters.

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?

A single short imperative sentence, front-loaded and free of waste. It is efficient, though it errs toward under-specification rather than over-verbosity.

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

Completeness2/5

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

A destructive multi-parameter write tool with no output schema and 60% undocumented parameters demands more: heading matching rules, failure behavior when the heading is missing, and the stale-write contract are all absent.

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

Parameters2/5

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

Schema description coverage is only 40%; path, content, and heading have no schema descriptions and the description does not compensate. It also ignores semantics like how 'heading' is matched (exact line, level-agnostic) or the role of expected_sha256 and agent_preset, leaving the core matching parameter ambiguous.

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

Purpose4/5

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

States a specific verb (insert) and resource (content before a markdown heading line). It distinguishes from md_insert_after_heading by direction, but does not clarify scope differences versus the section-based sibling md_insert_after_section or its own alias md.insert_before_section.

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

Usage Guidelines2/5

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

No when-to-use, when-not, or alternative routing guidance is provided. The agent must infer from sibling names alone whether to use this versus md_insert_before_section or md_insert_after_heading.

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

md_lintA
Read-only

Lint a markdown rules file for duplicate headings, dangerous git commands, and missing final newline. Returns object envelope {ok, path, issue_count, issues} (CLI lint-agents --json parity; not a bare array). isError stays false when issues are present; branch on ok / issue_count. Example: {"path": "AGENTS.md"}

NameRequiredDescriptionDefault
pathYesMarkdown file path, relative to working directory (typically AGENTS.md).

TDQS

A4.4/5.0
Behavior5/5

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

Annotations only cover readOnlyHint and openWorldHint, but the description adds genuinely new behavior: the return is an object envelope (not a bare array), and isError remains false when issues exist, so the agent must branch on ok/issue_count rather than on error state. That is exactly the kind of non-obvious semantics that prevents misuse.

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?

Front-loaded with the action, then the return contract, then the branching rule, then an example — no wasted sentences. The trailing example is mildly redundant with the schema's own 'typically AGENTS.md' note, and the parenthetical CLI-parity remark adds density without much payoff.

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?

With no output schema, the description takes on the burden of describing the return shape and does so explicitly (ok, path, issue_count, issues) along with the error-state contract. For a single read-only parameter tool, nothing an agent needs to call 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% for the single path parameter, so baseline is 3; the description goes slightly beyond by showing a concrete example invocation {"path": "AGENTS.md"}, reinforcing the expected relative-path form. It adds little else about the parameter, so it stops short of 5.

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?

Specific verb (lint) plus resource (markdown rules file) plus the exact checks performed (duplicate headings, dangerous git commands, missing final newline). This scope distinguishes it cleanly from mutating siblings like md_dedupe_headings and fix_whitespace, which fix rather than report.

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?

Usage is implied by the check list and the 'branch on ok / issue_count' note, which is about interpreting results rather than choosing the tool. It never states when to prefer this over md_dedupe_headings, fix_whitespace, or tidy_check, nor any prerequisites for the target file.

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

md_move_sectionA
Destructive

Move a markdown heading section to a new position (same file reorder or cross-file). Exactly one of before or after is required. Omit to for same-file reorder. Example: {"path": "spec.md", "heading": "## Appendix", "to": "notes.md", "before": "## References"}

NameRequiredDescriptionDefault
toNoDestination file path (relative to working directory). Omit for same-file reorder.
pathYesSource file path containing the section to move (relative to working directory).
afterNoInsert after this heading at the destination.
beforeNoInsert before this heading at the destination.
headingYesHeading of the section to move (e.g., "## FAQ").

TDQS

A4.2/5.0
Behavior3/5

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

Annotations already carry the safety profile (readOnlyHint=false, destructiveHint=true), and the description usefully adds the cross-file capability and the before/after exclusivity rule. It still doesn't say whether the destination file is created if absent, whether an existing section at the destination is overwritten, or what happens when the heading is not found.

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?

Four tight sentences with the purpose front-loaded, followed by the two operative constraints and a compact JSON example. No filler or redundancy.

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 mutation tool with no output schema and annotations covering safety, the description covers mode, constraints, and a worked example adequately. Remaining gaps are edge-case behaviors (missing destination file, heading-not-found, overwrite semantics) rather than core usage information.

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 parameter meaning is largely covered by the schema itself. The description still adds real value by stating the mutual-exclusivity constraint (exactly one of before/after) that the schema does not encode, since only path and heading are marked required.

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

Purpose5/5

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

States a specific verb (move) and resource (markdown heading section), and further scopes it with the two supported modes: same-file reorder and cross-file move. An agent can distinguish this from siblings like md_replace_section or doc_move without opening the schema.

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

Usage Guidelines4/5

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

Gives concrete invocation constraints: exactly one of before/after is required, and to is omitted for same-file reorders. However, it never names an alternative tool or says when to prefer this over md_replace_section or ast_move-style siblings, so routing guidance is incomplete.

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

md_replace_sectionA
Destructive

Replace the body of a markdown section identified by heading (section ends at the next same-or-higher-level heading; nested lower-level headings are included). Section ends at the next same-or-higher-level heading; nested lower-level headings are included in the replaced range. Prefer peer-level headings when siblings must survive. Example: {"content":"Run npm install.\n","path":"README.md","heading":"## Installation"}

NameRequiredDescriptionDefault
pathYes
contentYes
headingYes
agent_presetNoWhen true, replace uses the agent preset: unique, require_change, fuzzy floor 0.90, allow_absent_old false. Off unless set.
expected_sha256NoSHA-256 hex of the file's current bytes. If it does not match, the tool returns error_kind stale and writes nothing.

TDQS

A3.5/5.0
Behavior4/5

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

Annotations already cover the safety profile (destructiveHint=true, readOnlyHint=false), and the description adds genuinely non-obvious destruction scope: nested lower-level headings are swallowed by the replaced range, and peer-level headings are required to protect siblings. That is exactly the collateral-damage context a destructive tool needs, though it says nothing about error/stale behavior or whether a missing heading creates a section.

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

Conciseness3/5

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

The heading-scope rule is stated twice — once in the parenthetical and again in the immediately following sentence — which is pure redundancy and pushes the useful 'prefer peer-level headings' advice past the first read. The example is well-placed and front-loading is otherwise decent.

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

Completeness3/5

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

For a destructive, no-output-schema tool this covers the range-of-destruction question well, but leaves a significant unknown: what happens when the heading does not exist (error, no-op, or create?). It also never mentions the role of agent_preset or expected_sha256 guardrails, though those are documented in the schema itself.

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 only 40% (path, content, heading are undocumented in the schema), so the description must compensate. It does explain the critical `heading` parameter's matching semantics and the example demonstrates path and content format, but neither `content` (does it replace fully or merge?) nor `path` (overwrite vs create) is given meaning beyond the example.

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

Purpose4/5

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

Clear verb+resource: 'Replace the body of a markdown section identified by heading.' It precisely delimits the replaced range (up to the next same-or-higher-level heading, nested subheadings included) and provides a concrete example with path/heading/content. It does not explicitly name sibling alternatives such as md_move_section or md_insert_after_section, so it is clear but not sibling-differentiating.

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?

'Prefer peer-level headings when siblings must survive' gives one real selection heuristic, and the example clarifies the intended call shape. However, it never states when to use this versus md_insert_after_section, md_move_section, or md_upsert_bullet, leaving the agent to infer the boundary from names alone.

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

md_table_appendB
Destructive

Append a row to a markdown table under a heading. Example: {"row":"| GET | /health | Health check |","path":"README.md","heading":"## API"}

NameRequiredDescriptionDefault
rowYes
pathYes
headingYes
agent_presetNoWhen true, replace uses the agent preset: unique, require_change, fuzzy floor 0.90, allow_absent_old false. Off unless set.
expected_sha256NoSHA-256 hex of the file's current bytes. If it does not match, the tool returns error_kind stale and writes nothing.

TDQS

B3.2/5.0
Behavior2/5

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

Annotations already declare destructiveHint=true and readOnlyHint=false, so the write profile is covered. The description adds nothing behavioral: it does not say what happens if the heading is absent, whether a table is created when none exists, where in the table the row lands, or that the operation rewrites the file.

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?

One sentence of purpose followed immediately by a concrete call example; every token earns its place and the core action is front-loaded.

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

Completeness3/5

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

For a destructive mutation with no output schema, an agent still lacks the failure semantics that matter most: behavior when the heading or table does not exist, and whether the append is idempotent. The stale-file contract is documented on expected_sha256 in the schema rather than the description, which partly compensates.

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 only 40%, but the example pins down the two ambiguous required params: the pipe-delimited format of 'row' (which the schema leaves as a bare string with no description) and the '## API' style of 'heading'. The remaining two optional params carry their own schema descriptions, so the description covers the gap that matters.

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

Purpose4/5

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

States a specific verb (append) and resource (a row to a markdown table) plus the anchoring condition (under a heading), which cleanly separates it from md_upsert_bullet or md_insert_after_heading. It does not name any sibling explicitly, so an agent must still infer the boundary from the scope wording alone.

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

Usage Guidelines2/5

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

No statement of when to choose this over md_upsert_bullet, md_insert_after_section, or append_file, and no prerequisites or exclusions. The embedded example loosely demonstrates a call, but that is illustration, not guidance.

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

md_upsert_bulletA
Destructive

Insert or update a bullet point under a markdown heading. Idempotent: skipped if the bullet is already present. Example: {"bullet":"- Added new feature","path":"CHANGELOG.md","heading":"## Changes"}

NameRequiredDescriptionDefault
pathYes
bulletYesBullet text. Alias `content` matches CLI `--content` / other md ops.
headingYes
agent_presetNoWhen true, replace uses the agent preset: unique, require_change, fuzzy floor 0.90, allow_absent_old false. Off unless set.
expected_sha256NoSHA-256 hex of the file's current bytes. If it does not match, the tool returns error_kind stale and writes nothing.

TDQS

A3.7/5.0
Behavior3/5

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

Annotations already mark the tool as destructive and non-read-only, so the safety bar is lower. The description usefully adds that the operation is idempotent and skipped when the bullet is already present, but it does not clarify update semantics, permission needs, or how conflicts or stale state are handled.

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 sentences plus a compact example, front-loaded with the action and idempotency constraint. Every part earns its place and nothing is buried.

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

Completeness3/5

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

The description covers the core operation and idempotency but leaves meaningful gaps for a 5-parameter mutation tool with no output schema. It does not describe update behavior when the bullet differs, stale-write handling via expected_sha256, or the effect of agent_preset, so an agent still needs to inspect the schema for critical details.

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 60%, with path and heading undocumented in the schema. The example demonstrates the shape of path, heading, and bullet, which adds some value, but the description does not explain agent_preset, expected_sha256, or how bullet text is matched for idempotency. Baseline 3 is appropriate given partial schema coverage.

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

Purpose5/5

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

States a specific verb pair ('insert or update') and resource ('bullet point under a markdown heading'), with a concrete example. This is distinguishable from sibling markdown tools like md_insert_after_heading because it targets bullets and is idempotent.

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 implies usage through 'insert or update' and the idempotency condition, but it does not explicitly name alternatives or when-not-to-use cases. An agent can infer this is for bullet upserts, but routing against nearby tools such as md_insert_after_heading or doc_update is left to inference.

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

move_fileA
Destructive

Rename (move) a file. Use force=true to overwrite an existing destination. Example: {"to":"new.txt","from":"old.txt"}

NameRequiredDescriptionDefault
toYes
fromYes
forceNoIf true, overwrite the destination if it already exists.
agent_presetNoWhen true, replace uses the agent preset: unique, require_change, fuzzy floor 0.90, allow_absent_old false. Off unless set.
expected_sha256NoSHA-256 hex of the file's current bytes. If it does not match, the tool returns error_kind stale and writes nothing.

TDQS

A3.8/5.0
Behavior4/5

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

Annotations already declare destructiveHint=true, so the safety profile is known; the description adds the exact destructive condition — the destination is overwritten only when force=true. It remains silent on staleness/atomicity behavior and the agent_preset mode, which are nontrivial side effects for a mutating tool.

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 terse clauses: purpose first, then the overwrite control, then a compact argument example. Every sentence earns its place with no filler.

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

Completeness3/5

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

For a 5-parameter mutating tool with no output schema, the description covers the core action, overwrite semantics, and argument shape, but never touches the stale-detection contract (expected_sha256) or agent_preset. Those are left entirely to the schema, leaving the description only adequate.

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 60%, and the two undocumented parameters (from/to) are exactly the ones the description disambiguates with a concrete example mapping source to destination. force is also explained in prose, so the description compensates for the coverage gap rather than repeating the schema.

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

Purpose4/5

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

States a specific verb and resource ('Rename (move) a file') that clearly identifies the operation. It implicitly separates itself from symbol-level movers like ast_move by saying 'file', but never names a sibling or draws an explicit boundary.

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?

Gives one conditional ('Use force=true to overwrite an existing destination'), which is genuinely useful. However there is no when-not guidance, no mention of the concurrency/staleness path (expected_sha256), and no routing to alternatives like create_file or ast_move.

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

notebook_editA
Destructive

Replace the source of one Jupyter notebook cell by its id. Pass the new cell body as one string. It is stored as an nbformat array of lines. Cell type, outputs, and the rest of the file stay put. A missing id is no_matches. A duplicate id is ambiguous. This does not run the cell. Address the cell by its id, not by index. source is the whole new cell body as one string. Does not run the cell. Example: {"source":"import pandas as pd\ndf.head()\n","path":"analysis.ipynb","cell_id":"load"}

NameRequiredDescriptionDefault
pathYes
sourceYesNew cell body. Newlines become the notebook source line array.
cell_idYesCell `id` from the notebook. Not a 0-based index.
agent_presetNoWhen true, replace uses the agent preset: unique, require_change, fuzzy floor 0.90, allow_absent_old false. Off unless set.
expected_sha256NoSHA-256 hex of the file's current bytes. If it does not match, the tool returns error_kind stale and writes nothing.

TDQS

A4/5.0
Behavior4/5

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

Annotations already declare destructiveHint=true and openWorldHint=false, so the safety profile is partly covered. The description adds real behavioral context beyond that: a missing id yields no_matches, a duplicate id is ambiguous, the cell is not executed, and everything outside the source value stays put (atomic, non-destructive to the rest of the file). It never states whether the write is reversible or what a success response contains.

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

Conciseness3/5

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

Front-loaded with the core action and ends with a useful concrete example, but it burns space on duplication: "does not run the cell" appears twice and the one-string source rule is stated twice. Roughly two of its sentences do not earn their 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 mutation tool with no output schema and annotations that already flag destructiveness, the description covers the important operational facts: addressing by id, error kinds for missing/ambiguous ids, no execution, and preservation of the surrounding file. The main omission is any mention of the return payload shape implied by the named error kinds.

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 80%, so the schema already documents `source`, `cell_id`, `agent_preset`, and `expected_sha256`; only `path` is bare. The description mostly restates the schema (source as one string, stored as an nbformat line array; cell_id is not an index) rather than adding syntax or format detail, so the baseline 3 is right.

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

Purpose5/5

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

States a specific verb (replace), a precise resource (the source of one Jupyter notebook cell), and the addressing key (by id). It also explicitly carves itself away from a sibling concept ("This is not a `doc.set` on the raw JSON"), so an agent can distinguish it without opening another schema.

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 concrete usage rules: address the cell by id and not by index, and the operation does not execute the cell. It also delimits scope against `doc.set`. What it lacks is routing to the obvious alternatives (`replace_text`, `ast_replace`) when the target is not a notebook cell.

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

operation_schemaA
Read-only

Return the JSON schema for one plan operation. Pass op, for example doc.set. Use this for execute_plan field names. Does not run the operation. Example: {"op": "doc.set"}

NameRequiredDescriptionDefault
opYesPlan operation name, for example `doc.set`.

TDQS

A3.9/5.0
Behavior3/5

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

readOnlyHint=true and openWorldHint=false already tell the agent this is a safe, local, non-mutating read. 'Does not run the operation' reinforces that, but the description adds little else—no behavior for unknown ops, no error semantics, no note on schema size or caching.

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?

Front-loaded purpose followed by usage and an exclusion; four short sentences with no filler. The trailing JSON example is somewhat redundant with the input schema and slightly pads the definition.

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 one-parameter read-only introspection tool with no output schema, the description covers what it returns and why to call it. It could note the possible failure mode for an unrecognized op, but nothing essential is missing.

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

Parameters3/5

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

Schema coverage is 100% and the single parameter is fully described, so the schema already carries the burden. The description supplies only the illustrative value 'doc.set' (repeated in the schema example and the JSON snippet), adding no new meaning.

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

Purpose5/5

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

States a specific verb (Return) and resource (the JSON schema for one plan operation), which an agent can immediately distinguish from execute_plan (runs the plan) and explain_plan (describes it). The example op 'doc.set' makes the scope 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?

Explicitly ties usage to a sibling: 'Use this for execute_plan field names,' and adds the exclusion 'Does not run the operation.' Clear context, though it never mentions what to do for unknown/invalid op names or other alternatives.

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

prepend_fileA
Destructive

Prepend content to an existing file. Inserts the file's line ending after the new text when that text does not already end with one. Example: {"content":"// Copyright 2026\n","path":"src/main.rs"}

NameRequiredDescriptionDefault
pathYes
contentYes
agent_presetNoWhen true, replace uses the agent preset: unique, require_change, fuzzy floor 0.90, allow_absent_old false. Off unless set.
expected_sha256NoSHA-256 hex of the file's current bytes. If it does not match, the tool returns error_kind stale and writes nothing.

TDQS

A3.7/5.0
Behavior4/5

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

Annotations carry the safety profile (destructiveHint=true, openWorldHint=false), so the bar is lower. The description still adds real behavioral value by disclosing the line-ending insertion rule, which is not derivable from the schema or annotations. It does not, however, mention atomicity or that stale-SHA writes are rejected (left to the schema).

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?

Front-loaded verb+resource followed by one precise behavioral sentence and a compact example. Every element earns its place; nothing is padded.

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 mutation with no output schema, the description covers the core operation and its one non-obvious behavior (line-ending handling). Remaining gaps (staleness rejection, agent_preset semantics) are documented in the schema, so the definition is largely sufficient.

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 50%, so path and content are undocumented in the schema. The example clarifies how path and content are supplied (including an embedded newline), adding some meaning, but the description never touches agent_preset or expected_sha256, so it only partially compensates for the coverage gap.

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

Purpose4/5

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

States a specific verb+resource ("Prepend content to an existing file") that an agent can act on directly. It does not, however, name or distinguish itself from close siblings like append_file, create_file, or doc_prepend, so sibling selection still requires inference.

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 phrase "to an existing file" implies the file must already exist (guiding away from create_file), but no explicit when-to-use, prerequisites, or alternative is named. Usage is only implied, not stated.

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

read_fileB
Read-only

Read file contents with optional line range. Optional lines range uses start:end (1-based).

NameRequiredDescriptionDefault
pathYes
limitNoHow many lines to return, starting at `offset` (or line 1).
linesNoOptional line range (e.g., "10:25"). 1-based inclusive.
offsetNo1-based first line. Same window as Claude Code / Cursor `offset`.
end_lineNo1-based inclusive end. Alias of the right side of `lines`.
start_lineNo1-based inclusive start. Alias of the left side of `lines`.

TDQS

B3.3/5.0
Behavior3/5

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

Annotations already declare readOnlyHint=true and openWorldHint=false, so the safety profile is covered. The description adds that line ranges are 1-based, which is useful, but says nothing about how the overlapping addressing parameters (lines vs start_line/end_line vs offset/limit) interact or which takes precedence when combined.

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

Conciseness5/5

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

Two short sentences with zero filler; the core purpose is front-loaded and the format caveat follows immediately. Nothing could be trimmed without losing information.

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

Completeness3/5

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

With six parameters offering three overlapping ways to specify a range plus a limit, the definition does not explain how they compose, which is the main correctness risk for invocation. Annotations cover the safety side and no output schema is declared, so the remaining gap is specifically the range-parameter interaction.

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 83%, above the threshold where the schema does the heavy lifting, so a 3 is the baseline. The description's note that `lines` uses "start:end (1-based)" largely restates the schema's own description of that parameter and adds no precedence rule among the four overlapping range parameters.

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

Purpose4/5

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

States a specific verb and resource ("Read file contents") and names the line-range capability. It is separable from list_files and search_files, but does not explicitly distinguish itself from siblings like ast_read or doc_get, which also return content.

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

Usage Guidelines2/5

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

The description offers no when-to-use or when-not-to-use guidance and never mentions alternatives. An agent must infer from the name that this is the raw-file read path rather than the AST or doc readers in the sibling list.

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

replace_textA
Destructive

Replace text in a file. Literal by default; set regex=true for regex. Options: nth, insert_before, insert_after, case_insensitive, multiline, if_exists, whole_line, range, word_boundary, fuzzy, min_fuzzy_score, allow_absent_old. Set word_boundary=true to match only whole words (prevents 'SetupFile' matching inside 'BenchSetupFile'). Set whole_line=true to replace entire lines containing a match (use with new="" to delete lines). Fuzzy: when exact old is absent, refuse by default even if score ≥ min_fuzzy_score (#1758); set allow_absent_old=true only for deliberate approximate recovery. Prefer ast_rename for identifiers. Example: {"path": "README.md", "old": "1.0.0", "new": "2.0.0"}. Insert after anchor (mutually exclusive with new): {"path": "src/main.rs", "old": "use std::io;", "insert_after": "use std::fs;"}

NameRequiredDescriptionDefault
newNoText to replace with. Mutually exclusive with insert_before/insert_after. Alias `to` accepted because agents often emit that name (LLM prior).
nthNoReplace only the Nth match (1-based). Default: replace all.
oldYesText to find. Alias `from` accepted because agents often emit that name (LLM prior).
pathYesFile path (relative to working directory). Alias `file` matches CLI/batch.
fuzzyNoWhen exact match fails, try fuzzy/similarity fallback (#1668).
rangeNoRestrict matching to a line range (e.g. "10:50" or "10-50"). Requires whole_line=true.
regexNoUse regex mode for the `old` pattern.
strictNoRoll back all writes when format/validate lifecycle steps fail.
uniqueNoFail if the pattern matches more than once (enforce unambiguous edits).
if_existsNoReturn success even if no matches found (idempotent mode).
multilineNoEnable multiline matching (dot matches newlines in regex mode).
whole_lineNoReplace the entire line containing each match, not just the matched span. When combined with new="" this deletes matching lines.
agent_presetNoApply the agent replace preset for this call (unique, require_change, fuzzy floor 0.90, allow_absent_old false). Off unless set (#2614).
insert_afterNoInsert text after each match instead of replacing. Mutually exclusive with new/insert_before.
after_contextNoContext line(s) after the target. Enables anchor-based fallback matching when the exact `old` text is not found.
insert_beforeNoInsert text before each match instead of replacing. Mutually exclusive with new/insert_after.
word_boundaryNoMatch only at word boundaries. Prevents 'SetupFile' from matching inside 'BenchSetupFile'. Auto-escapes regex metacharacters.
before_contextNoContext line(s) before the target. Enables anchor-based fallback matching when the exact `old` text is not found.
require_changeNoZero matches is an error (fail closed). Softened when if_exists is true.
expected_sha256NoSHA-256 hex of the file's current bytes. Mismatch is `error_kind: stale`.
min_fuzzy_scoreNoReject fuzzy matches below this similarity floor (#1687). `None` = no floor.
allow_absent_oldNoAllow fuzzy apply when exact `old` is absent (#1758). Default false (fail closed; report best candidate without writing).
case_insensitiveNoCase-insensitive matching.
command_positionNoOnly rewrite shell command-position tokens (not arguments / longer words). Peels wrappers like sudo, timeout, busybox, flock, runuser, setsid.

TDQS

A4.2/5.0
Behavior4/5

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

Annotations already declare destructiveHint=true with readOnlyHint=false, so the safety profile is known. The description adds real behavioral context beyond that: fuzzy matching refuses by default even when a score clears the floor, and allow_absent_old gates deliberate approximate recovery. It stops short of describing sequencing/rollback semantics (strict) or stale-file handling.

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

Conciseness3/5

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

The lead sentence and the two JSON examples are front-loaded and high-value, but the middle "Options: nth, insert_before, insert_after, ..." enumeration is pure dumps of schema property names and does not earn its space at 100% coverage. Several clauses (word_boundary, whole_line) duplicate the schema text nearly verbatim.

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 24-parameter mutation tool with no output schema, the description covers the highest-risk semantics: default matching mode, fail-closed fuzzy behavior, delete-via-empty-new, and the ast_rename handoff. Remaining gaps (expected_sha256/stale errors, strict rollback, undo path) are at least documented in the schema, so completeness is good but not exhaustive.

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, but the description earns above baseline by supplying a worked insert_after example and spelling out the mutual exclusivity between new and insert_before/insert_after. Much of the "Options:" list merely restates parameter names the schema already documents.

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?

Starts with a specific verb+resource ("Replace text in a file") and immediately fixes the default mode (literal, regex opt-in). It also distinguishes itself from a sibling by routing identifier edits to ast_rename, so an agent can tell it apart without opening schemas.

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

Usage Guidelines4/5

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

Gives explicit routing for one alternative ("Prefer ast_rename for identifiers") and a when-to-use constraint for allow_absent_old ("only for deliberate approximate recovery"). It does not, however, clarify when to prefer this over batch_replace, apply_patch, or apply_fragment, which share the same neighborhood.

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

search_filesB
Read-only

Search text files for a pattern (regex by default, use literal=true for exact match). Supports advanced layered ignores for LLM agents: globs (include), exclude_patterns, custom_ignore_filenames (e.g. .agentignore), max_results. Other options: files_with_matches, files_without_match, count, case_insensitive, multiline, invert_match, assert_count, before/after_context. Canonical multi-root field is paths (array); singular path is accepted as an alias for one root (same as paths:[path]). Example: {"pattern": "TODO", "paths": ["src/"], "literal": true, "custom_ignore_filenames": [".agentignore"], "exclude_patterns": ["target/**"], "max_results": 20}

NameRequiredDescriptionDefault
pathNoSingle search root (LLM prior: most MCP tools use singular `path`). Equivalent to `paths: [path]` when `paths` is empty. If both are set, `paths` wins.
countNoOnly return match counts per file.
globsNoGlob include patterns (may be repeated). Supports parity with CLI --glob and library SearchOptions.
pathsNoPaths to search in, relative to working directory (defaults to working directory root). Canonical multi-root form. Prefer this when searching multiple roots.
contextNoLines of context around matches (shorthand for before_context + after_context).
literalNoTreat pattern as a literal string instead of regex.
patternYesPattern to search for.
multilineNoEnable multiline matching (dot matches newlines in regex mode).
max_resultsNoMax detailed results (0 = unlimited).
assert_countNoAssert that the total match count equals N. Returns exit code 0 if exact, 2 otherwise.
invert_matchNoShow lines that do NOT match the pattern.
after_contextNoLines of context after each match.
before_contextNoLines of context before each match.
case_insensitiveNoCase-insensitive matching.
exclude_patternsNoExclude glob patterns (in addition to ignore files).
files_with_matchesNoOnly return file paths with matches (not match details).
files_without_matchNoOnly return file paths with no matches (grep -L).
custom_ignore_filenamesNoCustom ignore filenames (e.g. .agentignore).

TDQS

B3.2/5.0
Behavior3/5

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

Annotations already declare readOnlyHint=true and openWorldHint=false, covering the safety profile. The description adds some context — regex-by-default behavior, layered ignore files for LLM agents, and output-mode names — but much of that restates what the 100%-covered schema already documents, and it says nothing about return format, exit codes, or limits beyond max_results.

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, then groups advanced ignore options, other flags, and a canonical field note before ending with an example. It is reasonably sized for an 18-parameter tool, though the enumeration of option names adds limited value beyond the already complete schema.

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

Completeness3/5

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

For an 18-parameter read-only search tool with no output schema, the description covers the main modes and ignore layering but omits the return format (match detail structure, count output, file-only outputs) and other operational details. It is adequate but leaves an agent guessing about what results look like.

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 fully documents all 18 parameters. The description adds a few clarifications such as regex-default and the canonical paths vs path alias, but these largely mirror the schema, and the example is illustrative rather than adding new semantic meaning. Baseline 3 is appropriate when the schema does the heavy lifting.

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

Purpose4/5

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

The description states a specific verb and resource: 'Search text files for a pattern', with default regex behavior and a literal option. It is clear what the tool does, but it never names or contrasts with siblings such as ast_search or list_files, so sibling differentiation is missing.

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

Usage Guidelines2/5

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

There is no explicit when-to-use guidance versus alternatives. The only conditional advice is 'use literal=true for exact match', which is parameter-level rather than tool-selection guidance, and no when-not-to-use or alternative tool is mentioned.

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

server_infoA
Read-only

Return server identity and workspace root: cwd, surface (full|core), tool_count, package version, MCP protocol_version from handshake, and optional recommendation (coding agents may prefer core). Prefer relative path parameters under cwd; absolute paths are allowed only when they resolve inside the workspace (AllowIfContained). Outside-workspace and ../ escapes are rejected.

NameRequiredDescriptionDefault

No parameters

TDQS

A4/5.0
Behavior4/5

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

Annotations already declare readOnlyHint=true and openWorldHint=false, so the safety profile is covered. The description adds useful behavioral context: it lists returned fields and states that absolute paths are allowed only if contained in the workspace, while outside-workspace and ../ escapes are rejected.

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

Conciseness3/5

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

The first sentence is front-loaded and informative, but the second sentence about relative and absolute path parameters is irrelevant to a zero-parameter server_info call. It adds length without helping an agent invoke this specific 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?

With no parameters, no output schema, and safety annotations already present, the description supplies enough context by enumerating return fields and explaining workspace path containment. It does not fully explain when to call the tool relative to siblings, but it is otherwise complete for a simple read-only info tool.

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

Parameters4/5

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

The tool has zero parameters, so the baseline is 4. The description's path-related guidance does not apply to this tool's input schema, which is empty.

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 and resource: it returns server identity and workspace root. It enumerates the exact return fields (cwd, surface, tool_count, package version, MCP protocol_version, optional recommendation), making its purpose distinct from every sibling tool.

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?

Usage is only implied by the tool name and the note that coding agents may prefer core; there is no explicit when-to-use guidance versus alternatives. The path-preference sentence gives workspace constraints but does not clarify when an agent should call server_info itself.

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

tidy_checkA
Read-only

Scan files for missing final newline, mixed EOL, and trailing whitespace (CLI tidy check). Read-only: does not rewrite files. Canonical field is paths (array); singular path is accepted as an alias for one root. Empty issues is ok:true. Issues present still return a tool success with error_kind changes_detected. Example: {"path": "src/"}

NameRequiredDescriptionDefault
pathNoSingle scan root. Equivalent to `paths: [path]` when `paths` is empty.
pathsNoScan roots relative to working directory (defaults to workspace root).

TDQS

A4.1/5.0
Behavior5/5

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

Beyond the readOnlyHint annotation, it discloses the outcome contract: empty issues yields ok:true, and issues present still returns tool success with error_kind changes_detected. That is the single most valuable behavioral fact for a linter-style tool and it is stated outright.

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?

Front-loaded with the purpose, then the read-only constraint, then parameter and result semantics, with a compact example at the end. Every sentence carries information; the telegraphic style is slightly dense but not padded.

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?

No output schema exists, and the description compensates by explaining result/error semantics. With only two optional, fully documented parameters and low complexity, an agent has everything needed to call it correctly.

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

Parameters3/5

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

Schema description coverage is 100%, so both `path` and `paths` are already documented in the schema, including the alias equivalence. The description restates the canonical/alias relationship rather than adding new syntax or precedence detail, so the baseline 3 applies.

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

Purpose4/5

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

The description names a specific verb (scan) and the exact conditions checked (missing final newline, mixed EOL, trailing whitespace), plus the CLI analogue `tidy check`. It does not name the sibling it contrasts with (fix_whitespace / batch_tidy), though the read-only clause implicitly separates it from the fixing tools.

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?

"Read-only: does not rewrite files" gives clear context that this is the detection half of the check/fix pair, which steers an agent away from mutating tools. It stops short of explicitly naming the fixing alternative or stating when-not-to-use conditions.

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

undo_listA
Read-only

List backup sessions created by --apply (including nested monorepo roots). Same as CLI patchloom undo --list. Returns items (timestamp, project_root, file_count, entries) plus warnings. Empty tree is error_kind no_matches. Example: {}

NameRequiredDescriptionDefault

No parameters

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 and openWorldHint=false. The description adds valuable behavioral context: it returns items with specific fields, warnings, and that an empty tree yields error_kind no_matches. This goes beyond what annotations provide.

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?

Efficiently covers purpose, return shape, edge case, and example in a few sentences. Front-loads the primary action.

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 zero-param read-only list tool, the description provides sufficient detail about what is returned and what happens on empty results. No output schema exists, so describing return items is appropriate.

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?

Zero parameters, so baseline is 4. The description correctly notes no arguments are needed via the example {}.

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

Purpose5/5

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

States a specific verb and resource: lists backup sessions created by --apply. It also names the sibling undo_restore implicitly by describing the list rather than restore operation, and clarifies nested monorepo roots.

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 references '--apply' and CLI equivalence, which implies usage context, but doesn't explicitly say when to use this vs undo_restore or other listing tools. The scope of 'backup sessions created by --apply' is a clue but not a complete when-to-use statement.

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

undo_restoreA
Destructive

Preview or restore files from a --apply backup session. Default is dry-run (applied:false, error_kind:changes_detected). Set apply=true to restore. Omit session to use the newest. Optional path[] restores only those session files (unknown path is no_matches). Paths stay inside the MCP workspace (AllowIfContained). Example: {"session": "<id-from-undo_list>", "apply": true}

NameRequiredDescriptionDefault
pathNoRestore only these session paths (same as CLI `--path`). Unknown path is `no_matches` and does not restore the rest of the session.
applyNoWhen true, restore files. Default false is a dry-run preview (`applied: false`, `error_kind: changes_detected`).
sessionNoSession timestamp from `undo_list`. Omit to use the newest session.

TDQS

A4.6/5.0
Behavior5/5

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

Annotations already flag destructiveHint=true and readOnlyHint=false, and the description adds substantial context beyond that: the default dry-run behavior, the applied:false / error_kind:changes_detected result shape, newest-session fallback, and the AllowIfContained workspace containment rule. This is meaningful behavioral detail an agent needs before a destructive call.

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?

Front-loads the core capability, then proceeds through default behavior, the apply flag, session fallback, path narrowing, and a concrete example with zero filler sentences.

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?

No output schema exists, and the description covers the important return signals (applied:false, error_kind:changes_detected, no_matches) plus containment and session fallback. It is nearly complete for a 3-param destructive tool; only a fuller enumeration of possible error_kind values or success shape is missing.

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

Parameters3/5

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

Schema description coverage is 100%, so apply, path, and session are already fully documented in the schema; the description largely restates them (with only the no_matches nuance repeated). Baseline 3 applies since the description adds little beyond the structured fields.

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

Purpose5/5

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

States a specific verb (preview or restore) plus resource (files from an --apply backup session), and explicitly distinguishes itself from the sibling undo_list by referencing '<id-from-undo_list>'. An agent can tell it apart from list_files/undo_list without opening the schema.

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

Usage Guidelines5/5

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

Explicit when-and-how: default dry-run, set apply=true to actually restore, omit session to use the newest, and path[] narrows to specific session files. It even names the failure mode (unknown path -> no_matches) so the agent knows not to expect partial restore.

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. 35 tool updatesv0.32.6
    • Changedappend_file2 fields changed
      • addedInput schema / properties / agent_preset
        Added value: +{
        +  "default": false,
        +  "description": "When true, replace uses the agent preset: unique, require_change, fuzzy floor 0.90, allow_absent_old false. Off unless set.",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / expected_sha256
        Added value: +{
        +  "description": "SHA-256 hex of the file's current bytes. If it does not match, the tool returns error_kind stale and writes nothing.",
        +  "type": "string"
        +}
    • Changedapply_fragment2 fields changed
      • addedInput schema / properties / agent_preset
        Added value: +{
        +  "default": false,
        +  "description": "When true, replace uses the agent preset: unique, require_change, fuzzy floor 0.90, allow_absent_old false. Off unless set.",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / expected_sha256
        Added value: +{
        +  "description": "SHA-256 hex of the file's current bytes. If it does not match, the tool returns error_kind stale and writes nothing.",
        +  "type": "string"
        +}
    • Changedapply_patch1 field changed
      • addedInput schema / properties / apply
        Added value: +{
        +  "default": true,
        +  "description": "When true (default), apply the patch. Set `apply=false` for check-only\npreview (CLI `patch check`; disk is unchanged).",
        +  "type": "boolean"
        +}
    • Addedast_delete_symbol
    • Addedast_replace_symbol
    • Changedcreate_file2 fields changed
      • addedInput schema / properties / agent_preset
        Added value: +{
        +  "default": false,
        +  "description": "When true, replace uses the agent preset: unique, require_change, fuzzy floor 0.90, allow_absent_old false. Off unless set.",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / expected_sha256
        Added value: +{
        +  "description": "SHA-256 hex of the file's current bytes. If it does not match, the tool returns error_kind stale and writes nothing.",
        +  "type": "string"
        +}
    • Changeddelete_file2 fields changed
      • addedInput schema / properties / agent_preset
        Added value: +{
        +  "default": false,
        +  "description": "When true, replace uses the agent preset: unique, require_change, fuzzy floor 0.90, allow_absent_old false. Off unless set.",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / expected_sha256
        Added value: +{
        +  "description": "SHA-256 hex of the file's current bytes. If it does not match, the tool returns error_kind stale and writes nothing.",
        +  "type": "string"
        +}
    • Changeddoc_append2 fields changed
      • addedInput schema / properties / agent_preset
        Added value: +{
        +  "default": false,
        +  "description": "When true, replace uses the agent preset: unique, require_change, fuzzy floor 0.90, allow_absent_old false. Off unless set.",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / expected_sha256
        Added value: +{
        +  "description": "SHA-256 hex of the file's current bytes. If it does not match, the tool returns error_kind stale and writes nothing.",
        +  "type": "string"
        +}
    • Changeddoc_delete2 fields changed
      • addedInput schema / properties / agent_preset
        Added value: +{
        +  "default": false,
        +  "description": "When true, replace uses the agent preset: unique, require_change, fuzzy floor 0.90, allow_absent_old false. Off unless set.",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / expected_sha256
        Added value: +{
        +  "description": "SHA-256 hex of the file's current bytes. If it does not match, the tool returns error_kind stale and writes nothing.",
        +  "type": "string"
        +}
    • Changeddoc_delete_where2 fields changed
      • addedInput schema / properties / agent_preset
        Added value: +{
        +  "default": false,
        +  "description": "When true, replace uses the agent preset: unique, require_change, fuzzy floor 0.90, allow_absent_old false. Off unless set.",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / expected_sha256
        Added value: +{
        +  "description": "SHA-256 hex of the file's current bytes. If it does not match, the tool returns error_kind stale and writes nothing.",
        +  "type": "string"
        +}
    • Changeddoc_ensure2 fields changed
      • addedInput schema / properties / agent_preset
        Added value: +{
        +  "default": false,
        +  "description": "When true, replace uses the agent preset: unique, require_change, fuzzy floor 0.90, allow_absent_old false. Off unless set.",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / expected_sha256
        Added value: +{
        +  "description": "SHA-256 hex of the file's current bytes. If it does not match, the tool returns error_kind stale and writes nothing.",
        +  "type": "string"
        +}
    • Changeddoc_merge2 fields changed
      • addedInput schema / properties / agent_preset
        Added value: +{
        +  "default": false,
        +  "description": "When true, replace uses the agent preset: unique, require_change, fuzzy floor 0.90, allow_absent_old false. Off unless set.",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / expected_sha256
        Added value: +{
        +  "description": "SHA-256 hex of the file's current bytes. If it does not match, the tool returns error_kind stale and writes nothing.",
        +  "type": "string"
        +}
    • Changeddoc_move2 fields changed
      • addedInput schema / properties / agent_preset
        Added value: +{
        +  "default": false,
        +  "description": "When true, replace uses the agent preset: unique, require_change, fuzzy floor 0.90, allow_absent_old false. Off unless set.",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / expected_sha256
        Added value: +{
        +  "description": "SHA-256 hex of the file's current bytes. If it does not match, the tool returns error_kind stale and writes nothing.",
        +  "type": "string"
        +}
    • Changeddoc_prepend2 fields changed
      • addedInput schema / properties / agent_preset
        Added value: +{
        +  "default": false,
        +  "description": "When true, replace uses the agent preset: unique, require_change, fuzzy floor 0.90, allow_absent_old false. Off unless set.",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / expected_sha256
        Added value: +{
        +  "description": "SHA-256 hex of the file's current bytes. If it does not match, the tool returns error_kind stale and writes nothing.",
        +  "type": "string"
        +}
    • Changeddoc_set2 fields changed
      • addedInput schema / properties / agent_preset
        Added value: +{
        +  "default": false,
        +  "description": "When true, replace uses the agent preset: unique, require_change, fuzzy floor 0.90, allow_absent_old false. Off unless set.",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / expected_sha256
        Added value: +{
        +  "description": "SHA-256 hex of the file's current bytes. If it does not match, the tool returns error_kind stale and writes nothing.",
        +  "type": "string"
        +}
    • Changeddoc_update2 fields changed
      • addedInput schema / properties / agent_preset
        Added value: +{
        +  "default": false,
        +  "description": "When true, replace uses the agent preset: unique, require_change, fuzzy floor 0.90, allow_absent_old false. Off unless set.",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / expected_sha256
        Added value: +{
        +  "description": "SHA-256 hex of the file's current bytes. If it does not match, the tool returns error_kind stale and writes nothing.",
        +  "type": "string"
        +}
    • Changedexecute_plan8 fields changed
      • removedInput schema / $defs
        Removed value: -{
        -  "ForEach": {
        -    "description": "Glob-driven batch expansion: apply the same set of operations to every\nfile matching a glob pattern, with template variable substitution.",
        -    "properties": {
        -      "exclude": {
        -        "default": [],
        -        "description": "Glob patterns to exclude from the matched set.",
        -        "items": {
        -          "type": "string"
        -        },
        -        "type": "array"
        -      },
        -      "filter": {
        -        "default": null,
        -        "description": "Optional filter expression (e.g. `has_symbol(tests)`).",
        -        "type": [
        -          "string",
        -          "null"
        -        ]
        -      },
        -      "glob": {
        -        "description": "Glob pattern to expand (e.g. `src/**/*.rs`).",
        -        "type": "string"
        -      }
        -    },
        -    "required": [
        -      "glob"
        -    ],
        -    "type": "object"
        -  },
        -  "FormatStep": {
        -    "description": "A format step to run after applying operations but before validation.",
        -    "properties": {
        -      "cmd": {
        -        "type": "string"
        -      },
        -      "timeout": {
        -        "description": "Timeout in seconds (default: 60).",
        -        "format": "uint64",
        -        "minimum": 0,
        -        "type": [
        -          "integer",
        -          "null"
        -        ]
        -      }
        -    },
        -    "required": [
        -      "cmd"
        -    ],
        -    "type": "object"
        -  },
        -  "OnStale": {
        -    "enum": [
        -      "fail",
        -      "merge"
        -    ],
        -    "type": "string"
        -  },
        -  "Operation": {
        -    "description": "A single operation within a plan.",
        -    "oneOf": [
        -      {
        -        "properties": {
        -          "after_context": {
        -            "description": "Context line(s) after the target for anchor-based fallback matching.",
        -            "type": [
        -              "string",
        -              "null"
        -            ]
        -          },
        -          "allow_absent_old": {
        -            "default": false,
        -            "description": "When exact `old` is absent, allow Similarity/fuzzy apply of a nearby\nspan (historical default). When false (default), refuse the write and\nreport the best candidate (#1758). Anchored context matches still apply.",
        -            "type": "boolean"
        -          },
        -          "before_context": {
        -            "description": "Context line(s) before the target for anchor-based fallback matching.",
        -            "type": [
        -              "string",
        -              "null"
        -            ]
        -          },
        -          "case_insensitive": {
        -            "default": false,
        -            "description": "Case-insensitive matching.",
        -            "type": "boolean"
        -          },
        -          "command_position": {
        -            "default": false,
        -            "description": "Only rewrite shell command-position tokens (not arguments / longer words).\nLiteral only; incompatible with regex/case_insensitive/word_boundary/fuzzy.",
        -            "type": "boolean"
        -          },
        -          "fuzzy": {
        -            "default": false,
        -            "description": "When exact match fails, try fuzzy/similarity fallback (library/plan/MCP).\nAlso enabled implicitly when before_context/after_context is set.",
        -            "type": "boolean"
        -          },
        -          "glob": {
        -            "description": "Glob pattern to match files (e.g. \"src/**/*.rs\"). Mutually exclusive with path.",
        -            "type": [
        -              "string",
        -              "null"
        -            ]
        -          },
        -          "if_exists": {
        -            "default": false,
        -            "description": "Return success even if no matches found (idempotent mode).",
        -            "type": "boolean"
        -          },
        -          "insert_after": {
        -            "description": "Insert text after each match instead of replacing.",
        -            "type": [
        -              "string",
        -              "null"
        -            ]
        -          },
        -          "insert_before": {
        -            "description": "Insert text before each match instead of replacing.",
        -            "type": [
        -              "string",
        -              "null"
        -            ]
        -          },
        -          "min_fuzzy_score": {
        -            "default": null,
        -            "description": "Reject fuzzy matches below this score when set (#1687).",
        -            "format": "double",
        -            "type": [
        -              "number",
        -              "null"
        -            ]
        -          },
        -          "multiline": {
        -            "default": false,
        -            "description": "Enable multiline matching (dot matches newlines in regex mode).",
        -            "type": "boolean"
        -          },
        -          "new": {
        -            "description": "Replacement text. Supports $1/$2 capture group references in regex mode.\nAlias `to` accepted because agents often emit that name (LLM prior).",
        -            "type": [
        -              "string",
        -              "null"
        -            ]
        -          },
        -          "nth": {
        -            "description": "Replace only the Nth occurrence (1-based).",
        -            "format": "uint",
        -            "minimum": 0,
        -            "type": [
        -              "integer",
        -              "null"
        -            ]
        -          },
        -          "old": {
        -            "description": "Pattern to find (literal string or regex).\nAlias `from` accepted because agents often emit that name (LLM prior).",
        -            "type": "string"
        -          },
        -          "op": {
        -            "const": "replace",
        -            "type": "string"
        -          },
        -          "path": {
        -            "description": "File path to replace in. Mutually exclusive with glob.\nAlias `file` matches MCP replace_text / LLM prior (#fixloop).",
        -            "type": [
        -              "string",
        -              "null"
        -            ]
        -          },
        -          "range": {
        -            "description": "Line range restriction (e.g. \"10:50\"). Only valid with whole_line.",
        -            "type": [
        -              "string",
        -              "null"
        -            ]
        -          },
        -          "regex": {
        -            "default": false,
        -            "description": "Treat `old` as a regex pattern.",
        -            "type": "boolean"
        -          },
        -          "require_change": {
        -            "default": false,
        -            "description": "Zero matches is an error (library fail-closed). Soft no-match when false.\nWhen both this and `if_exists` are true, `if_exists` wins.",
        -            "type": "boolean"
        -          },
        -          "unique": {
        -            "default": false,
        -            "description": "Fail if the pattern matches more than once (enforce unambiguous edits).",
        -            "type": "boolean"
        -          },
        -          "whole_line": {
        -            "default": false,
        -            "description": "Replace the entire line containing each match, not just the matched span.",
        -            "type": "boolean"
        -          },
        -          "word_boundary": {
        -            "default": false,
        -            "description": "Match only at word boundaries (\\b). Prevents partial matches.",
        -            "type": "boolean"
        -          }
        -        },
        -        "required": [
        -          "op",
        -          "old"
        -        ],
        -        "type": "object"
        -      },
        -      {
        -        "description": "Constrained freeform fragment apply (#2018): Morph-style marker strip + required anchor.\n\nExactly one of `after`, `before`, or `old` must be set. Fragment may include\n`// ... existing code ...` lines (stripped). No model merge / no anchor-less guess.",
        -        "properties": {
        -          "after": {
        -            "default": null,
        -            "description": "Insert cleaned fragment after this unique anchor.",
        -            "type": [
        -              "string",
        -              "null"
        -            ]
        -          },
        -          "before": {
        -            "default": null,
        -            "description": "Insert cleaned fragment before this unique anchor.",
        -            "type": [
        -              "string",
        -              "null"
        -            ]
        -          },
        -          "fragment": {
        -            "description": "New text or Morph-style snippet (lazy marker lines stripped).\nAliases `new`/`to`/`content` match replace_text agent priors.",
        -            "type": "string"
        -          },
        -          "instruction": {
        -            "default": null,
        -            "description": "Optional human instruction (explain only; not used for merge).",
        -            "type": [
        -              "string",
        -              "null"
        -            ]
        -          },
        -          "old": {
        -            "default": null,
        -            "description": "Replace this unique span with the cleaned fragment.",
        -            "type": [
        -              "string",
        -              "null"
        -            ]
        -          },
        -          "op": {
        -            "const": "apply.fragment",
        -            "type": "string"
        -          },
        -          "path": {
        -            "description": "File to edit.",
        -            "type": "string"
        -          },
        -          "unique": {
        -            "default": true,
        -            "description": "Fail if the anchor matches more than once (default true).",
        -            "type": "boolean"
        -          }
        -        },
        -        "required": [
        -          "op",
        -          "path",
        -          "fragment"
        -        ],
        -        "type": "object"
        -      },
        -      {
        -        "properties": {
        -          "if_exists": {
        -            "default": false,
        -            "description": "Soft-skip (no write) when the file is missing or the selector is\nnot present. Default false: missing file is `not_found`; a missing\nselector creates the key.",
        -            "type": "boolean"
        -          },
        -          "op": {
        -            "const": "doc.set",
        -            "type": "string"
        -          },
        -          "path": {
        -            "description": "Path to the JSON, YAML, or TOML file.",
        -            "type": "string"
        -          },
        -          "selector": {
        -            "description": "Dot-notation selector path (e.g. \"server.port\", \"env.0.value\").\n`.` (or empty / `/`) is the document root and replaces the whole value.\nAlias `key` accepted because agents often emit that name (LLM prior).",
        -            "type": "string"
        -          },
        -          "value": {
        -            "description": "Value to set (any JSON type)."
        -          }
        -        },
        -        "required": [
        -          "op",
        -          "path",
        -          "selector",
        -          "value"
        -        ],
        -        "type": "object"
        -      },
        -      {
        -        "properties": {
        -          "op": {
        -            "const": "doc.delete",
        -            "type": "string"
        -          },
        -          "path": {
        -            "description": "Path to the JSON, YAML, or TOML file.",
        -            "type": "string"
        -          },
        -          "selector": {
        -            "description": "Dot-notation selector path to delete.",
        -            "type": "string"
        -          }
        -        },
        -        "required": [
        -          "op",
        -          "path",
        -          "selector"
        -        ],
        -        "type": "object"
        -      },
        -      {
        -        "properties": {
        -          "op": {
        -            "const": "doc.merge",
        -            "type": "string"
        -          },
        -          "path": {
        -            "description": "Path to the JSON, YAML, or TOML file.",
        -            "type": "string"
        -          },
        -          "selector": {
        -            "description": "Optional selector for the merge target (e.g. `0` for multi-doc YAML).\nWhen omitted, merges into the document root.",
        -            "type": [
        -              "string",
        -              "null"
        -            ]
        -          },
        -          "value": {
        -            "description": "Object to deep-merge into the file (or selected object)."
        -          }
        -        },
        -        "required": [
        -          "op",
        -          "path",
        -          "value"
        -        ],
        -        "type": "object"
        -      },
        -      {
        -        "properties": {
        -          "op": {
        -            "const": "doc.append",
        -            "type": "string"
        -          },
        -          "path": {
        -            "description": "Path to the JSON, YAML, or TOML file.",
        -            "type": "string"
        -          },
        -          "selector": {
        -            "description": "Dot-notation selector path to an array.",
        -            "type": "string"
        -          },
        -          "value": {
        -            "description": "Value to append to the array."
        -          }
        -        },
        -        "required": [
        -          "op",
        -          "path",
        -          "selector",
        -          "value"
        -        ],
        -        "type": "object"
        -      },
        -      {
        -        "properties": {
        -          "op": {
        -            "const": "doc.prepend",
        -            "type": "string"
        -          },
        -          "path": {
        -            "description": "Path to the JSON, YAML, or TOML file.",
        -            "type": "string"
        -          },
        -          "selector": {
        -            "description": "Dot-notation selector path to an array.",
        -            "type": "string"
        -          },
        -          "value": {
        -            "description": "Value to prepend to the array."
        -          }
        -        },
        -        "required": [
        -          "op",
        -          "path",
        -          "selector",
        -          "value"
        -        ],
        -        "type": "object"
        -      },
        -      {
        -        "properties": {
        -          "op": {
        -            "const": "doc.update",
        -            "type": "string"
        -          },
        -          "path": {
        -            "description": "Path to the JSON, YAML, or TOML file.",
        -            "type": "string"
        -          },
        -          "selector": {
        -            "description": "Dot-notation selector path (supports wildcards and predicates).",
        -            "type": "string"
        -          },
        -          "value": {
        -            "description": "New value for all matching locations."
        -          }
        -        },
        -        "required": [
        -          "op",
        -          "path",
        -          "selector",
        -          "value"
        -        ],
        -        "type": "object"
        -      },
        -      {
        -        "properties": {
        -          "from": {
        -            "description": "Dot-notation source path.",
        -            "type": "string"
        -          },
        -          "op": {
        -            "const": "doc.move",
        -            "type": "string"
        -          },
        -          "path": {
        -            "description": "Path to the JSON, YAML, or TOML file.",
        -            "type": "string"
        -          },
        -          "to": {
        -            "description": "Dot-notation destination path.",
        -            "type": "string"
        -          }
        -        },
        -        "required": [
        -          "op",
        -          "path",
        -          "from",
        -          "to"
        -        ],
        -        "type": "object"
        -      },
        -      {
        -        "properties": {
        -          "op": {
        -            "const": "doc.ensure",
        -            "type": "string"
        -          },
        -          "path": {
        -            "description": "Path to the JSON, YAML, or TOML file.",
        -            "type": "string"
        -          },
        -          "selector": {
        -            "description": "Dot-notation selector path.",
        -            "type": "string"
        -          },
        -          "value": {
        -            "description": "Value to set only if the key does not already exist."
        -          }
        -        },
        -        "required": [
        -          "op",
        -          "path",
        -          "selector",
        -          "value"
        -        ],
        -        "type": "object"
        -      },
        -      {
        -        "properties": {
        -          "op": {
        -            "const": "doc.delete_where",
        -            "type": "string"
        -          },
        -          "path": {
        -            "description": "Path to the JSON, YAML, or TOML file.",
        -            "type": "string"
        -          },
        -          "predicate": {
        -            "description": "Predicate in \"field=value\" format to match elements for deletion.",
        -            "type": "string"
        -          },
        -          "selector": {
        -            "description": "Dot-notation selector path to an array.",
        -            "type": "string"
        -          }
        -        },
        -        "required": [
        -          "op",
        -          "path",
        -          "selector",
        -          "predicate"
        -        ],
        -        "type": "object"
        -      },
        -      {
        -        "properties": {
        -          "content": {
        -            "type": "string"
        -          },
        -          "heading": {
        -            "type": "string"
        -          },
        -          "op": {
        -            "const": "md.replace_section",
        -            "type": "string"
        -          },
        -          "path": {
        -            "type": "string"
        -          }
        -        },
        -        "required": [
        -          "op",
        -          "path",
        -          "heading",
        -          "content"
        -        ],
        -        "type": "object"
        -      },
        -      {
        -        "properties": {
        -          "content": {
        -            "type": "string"
        -          },
        -          "heading": {
        -            "type": "string"
        -          },
        -          "op": {
        -            "const": "md.insert_after_heading",
        -            "type": "string"
        -          },
        -          "path": {
        -            "type": "string"
        -          }
        -        },
        -        "required": [
        -          "op",
        -          "path",
        -          "heading",
        -          "content"
        -        ],
        -        "type": "object"
        -      },
        -      {
        -        "description": "Insert after the full section body (sibling placement). #1726",
        -        "properties": {
        -          "content": {
        -            "type": "string"
        -          },
        -          "heading": {
        -            "type": "string"
        -          },
        -          "op": {
        -            "const": "md.insert_after_section",
        -            "type": "string"
        -          },
        -          "path": {
        -            "type": "string"
        -          }
        -        },
        -        "required": [
        -          "op",
        -          "path",
        -          "heading",
        -          "content"
        -        ],
        -        "type": "object"
        -      },
        -      {
        -        "description": "Alias `md.insert_before_section`: section start == heading line.",
        -        "properties": {
        -          "content": {
        -            "type": "string"
        -          },
        -          "heading": {
        -            "type": "string"
        -          },
        -          "op": {
        -            "const": "md.insert_before_heading",
        -            "type": "string"
        -          },
        -          "path": {
        -            "type": "string"
        -          }
        -        },
        -        "required": [
        -          "op",
        -          "path",
        -          "heading",
        -          "content"
        -        ],
        -        "type": "object"
        -      },
        -      {
        -        "properties": {
        -          "bullet": {
        -            "description": "Bullet text. Alias `content` matches CLI `--content` / other md ops.",
        -            "type": "string"
        -          },
        -          "heading": {
        -            "type": "string"
        -          },
        -          "op": {
        -            "const": "md.upsert_bullet",
        -            "type": "string"
        -          },
        -          "path": {
        -            "type": "string"
        -          }
        -        },
        -        "required": [
        -          "op",
        -          "path",
        -          "heading",
        -          "bullet"
        -        ],
        -        "type": "object"
        -      },
        -      {
        -        "properties": {
        -          "heading": {
        -            "type": "string"
        -          },
        -          "op": {
        -            "const": "md.table_append",
        -            "type": "string"
        -          },
        -          "path": {
        -            "type": "string"
        -          },
        -          "row": {
        -            "type": "string"
        -          }
        -        },
        -        "required": [
        -          "op",
        -          "path",
        -          "heading",
        -          "row"
        -        ],
        -        "type": "object"
        -      },
        -      {
        -        "properties": {
        -          "after": {
        -            "description": "Insert after this heading at the destination.",
        -            "type": [
        -              "string",
        -              "null"
        -            ]
        -          },
        -          "before": {
        -            "description": "Insert before this heading at the destination.",
        -            "type": [
        -              "string",
        -              "null"
        -            ]
        -          },
        -          "heading": {
        -            "type": "string"
        -          },
        -          "op": {
        -            "const": "md.move_section",
        -            "type": "string"
        -          },
        -          "path": {
        -            "type": "string"
        -          },
        -          "to": {
        -            "description": "Destination file. When omitted, reorder within the same file.",
        -            "type": [
        -              "string",
        -              "null"
        -            ]
        -          }
        -        },
        -        "required": [
        -          "op",
        -          "path",
        -          "heading"
        -        ],
        -        "type": "object"
        -      },
        -      {
        -        "properties": {
        -          "op": {
        -            "const": "md.dedupe_headings",
        -            "type": "string"
        -          },
        -          "path": {
        -            "type": "string"
        -          }
        -        },
        -        "required": [
        -          "op",
        -          "path"
        -        ],
        -        "type": "object"
        -      },
        -      {
        -        "properties": {
        -          "collapse_blanks": {
        -            "description": "Collapse consecutive blank lines into a single blank line.",
        -            "type": [
        -              "boolean",
        -              "null"
        -            ]
        -          },
        -          "dedent": {
        -            "description": "Dedent specification: \"4\", \"tab\", or \"auto\".",
        -            "type": [
        -              "string",
        -              "null"
        -            ]
        -          },
        -          "ensure_final_newline": {
        -            "type": [
        -              "boolean",
        -              "null"
        -            ]
        -          },
        -          "indent": {
        -            "description": "Indent specification: \"4\", \"tab\".",
        -            "type": [
        -              "string",
        -              "null"
        -            ]
        -          },
        -          "lines": {
        -            "description": "Line range restriction for dedent/indent: \"10:50\" (1-based inclusive).",
        -            "type": [
        -              "string",
        -              "null"
        -            ]
        -          },
        -          "normalize_eol": {
        -            "type": [
        -              "string",
        -              "null"
        -            ]
        -          },
        -          "op": {
        -            "const": "tidy.fix",
        -            "type": "string"
        -          },
        -          "path": {
        -            "type": "string"
        -          },
        -          "trim_trailing_whitespace": {
        -            "type": [
        -              "boolean",
        -              "null"
        -            ]
        -          }
        -        },
        -        "required": [
        -          "op",
        -          "path"
        -        ],
        -        "type": "object"
        -      },
        -      {
        -        "properties": {
        -          "content": {
        -            "type": "string"
        -          },
        -          "force": {
        -            "type": [
        -              "boolean",
        -              "null"
        -            ]
        -          },
        -          "op": {
        -            "const": "file.create",
        -            "type": "string"
        -          },
        -          "path": {
        -            "type": "string"
        -          }
        -        },
        -        "required": [
        -          "op",
        -          "path",
        -          "content"
        -        ],
        -        "type": "object"
        -      },
        -      {
        -        "properties": {
        -          "content": {
        -            "type": "string"
        -          },
        -          "op": {
        -            "const": "file.append",
        -            "type": "string"
        -          },
        -          "path": {
        -            "type": "string"
        -          }
        -        },
        -        "required": [
        -          "op",
        -          "path",
        -          "content"
        -        ],
        -        "type": "object"
        -      },
        -      {
        -        "properties": {
        -          "content": {
        -            "type": "string"
        -          },
        -          "op": {
        -            "const": "file.prepend",
        -            "type": "string"
        -          },
        -          "path": {
        -            "type": "string"
        -          }
        -        },
        -        "required": [
        -          "op",
        -          "path",
        -          "content"
        -        ],
        -        "type": "object"
        -      },
        -      {
        -        "properties": {
        -          "if_exists": {
        -            "default": false,
        -            "description": "Soft-skip (no write) when the file is missing. Default false:\nmissing path is `not_found`.",
        -            "type": "boolean"
        -          },
        -          "op": {
        -            "const": "file.delete",
        -            "type": "string"
        -          },
        -          "path": {
        -            "description": "Path of the file to delete.",
        -            "type": "string"
        -          }
        -        },
        -        "required": [
        -          "op",
        -          "path"
        -        ],
        -        "type": "object"
        -      },
        -      {
        -        "properties": {
        -          "force": {
        -            "default": false,
        -            "description": "If true, overwrite the destination if it already exists.",
        -            "type": "boolean"
        -          },
        -          "from": {
        -            "type": "string"
        -          },
        -          "op": {
        -            "const": "file.rename",
        -            "type": "string"
        -          },
        -          "to": {
        -            "type": "string"
        -          }
        -        },
        -        "required": [
        -          "op",
        -          "from",
        -          "to"
        -        ],
        -        "type": "object"
        -      },
        -      {
        -        "properties": {
        -          "allow_conflicts": {
        -            "default": false,
        -            "type": "boolean"
        -          },
        -          "diff": {
        -            "type": "string"
        -          },
        -          "on_stale": {
        -            "$ref": "#/$defs/OnStale",
        -            "default": "fail"
        -          },
        -          "op": {
        -            "const": "patch.apply",
        -            "type": "string"
        -          },
        -          "replace_all": {
        -            "default": false,
        -            "description": "SEARCH/REPLACE only: update every exact match. Default unique.",
        -            "type": "boolean"
        -          }
        -        },
        -        "required": [
        -          "op",
        -          "diff"
        -        ],
        -        "type": "object"
        -      },
        -      {
        -        "properties": {
        -          "after_context": {
        -            "format": "uint",
        -            "minimum": 0,
        -            "type": [
        -              "integer",
        -              "null"
        -            ]
        -          },
        -          "assert_count": {
        -            "description": "Assert that the total match count equals N. Fails the operation otherwise.",
        -            "format": "uint",
        -            "minimum": 0,
        -            "type": [
        -              "integer",
        -              "null"
        -            ]
        -          },
        -          "before_context": {
        -            "format": "uint",
        -            "minimum": 0,
        -            "type": [
        -              "integer",
        -              "null"
        -            ]
        -          },
        -          "case_insensitive": {
        -            "default": false,
        -            "type": "boolean"
        -          },
        -          "context": {
        -            "format": "uint",
        -            "minimum": 0,
        -            "type": [
        -              "integer",
        -              "null"
        -            ]
        -          },
        -          "custom_ignore_filenames": {
        -            "default": [],
        -            "items": {
        -              "type": "string"
        -            },
        -            "type": "array"
        -          },
        -          "exclude_patterns": {
        -            "default": [],
        -            "items": {
        -              "type": "string"
        -            },
        -            "type": "array"
        -          },
        -          "globs": {
        -            "default": [],
        -            "items": {
        -              "type": "string"
        -            },
        -            "type": "array"
        -          },
        -          "invert_match": {
        -            "default": false,
        -            "description": "Show lines that do NOT match the pattern.",
        -            "type": "boolean"
        -          },
        -          "literal": {
        -            "default": false,
        -            "type": "boolean"
        -          },
        -          "max_results": {
        -            "default": 0,
        -            "format": "uint",
        -            "minimum": 0,
        -            "type": "integer"
        -          },
        -          "multiline": {
        -            "default": false,
        -            "description": "Enable multiline matching (dot matches newlines in regex mode).",
        -            "type": "boolean"
        -          },
        -          "op": {
        -            "const": "search",
        -            "type": "string"
        -          },
        -          "path": {
        -            "type": "string"
        -          },
        -          "pattern": {
        -            "type": "string"
        -          },
        -          "regex": {
        -            "default": false,
        -            "type": "boolean"
        -          }
        -        },
        -        "required": [
        -          "op",
        -          "path",
        -          "pattern"
        -        ],
        -        "type": "object"
        -      },
        -      {
        -        "properties": {
        -          "lines": {
        -            "description": "Optional line range (e.g., \"10:25\").",
        -            "type": [
        -              "string",
        -              "null"
        -            ]
        -          },
        -          "op": {
        -            "const": "read",
        -            "type": "string"
        -          },
        -          "path": {
        -            "type": "string"
        -          }
        -        },
        -        "required": [
        -          "op",
        -          "path"
        -        ],
        -        "type": "object"
        -      },
        -      {
        -        "properties": {
        -          "op": {
        -            "const": "md.lint_agents",
        -            "type": "string"
        -          },
        -          "path": {
        -            "type": "string"
        -          }
        -        },
        -        "required": [
        -          "op",
        -          "path"
        -        ],
        -        "type": "object"
        -      },
        -      {
        -        "properties": {
        -          "lang": {
        -            "default": null,
        -            "description": "Language hint (e.g. \"rust\", \"go\"). Overrides extension-based detection.",
        -            "type": [
        -              "string",
        -              "null"
        -            ]
        -          },
        -          "new": {
        -            "description": "The new identifier name (same field name as replace / ast.replace JSON `new`).\nAlias `to` matches replace/ast.replace agent priors.",
        -            "type": "string"
        -          },
        -          "old": {
        -            "description": "The identifier to rename (same field name as replace / ast.replace).\nAlias `from` matches replace/ast.replace agent priors.",
        -            "type": "string"
        -          },
        -          "op": {
        -            "const": "ast.rename",
        -            "type": "string"
        -          },
        -          "path": {
        -            "description": "File or directory to rename in. Directories are walked recursively.",
        -            "type": "string"
        -          }
        -        },
        -        "required": [
        -          "op",
        -          "path",
        -          "old",
        -          "new"
        -        ],
        -        "type": "object"
        -      },
        -      {
        -        "properties": {
        -          "lang": {
        -            "default": null,
        -            "description": "Language hint (e.g. \"rust\", \"go\"). Overrides extension-based detection.",
        -            "type": [
        -              "string",
        -              "null"
        -            ]
        -          },
        -          "new": {
        -            "description": "Replacement text.",
        -            "type": "string"
        -          },
        -          "old": {
        -            "description": "Text or pattern to find within the symbol body.",
        -            "type": "string"
        -          },
        -          "op": {
        -            "const": "ast.replace",
        -            "type": "string"
        -          },
        -          "path": {
        -            "description": "File to replace in.",
        -            "type": "string"
        -          },
        -          "regex": {
        -            "default": false,
        -            "description": "Treat `old` as a regex pattern.",
        -            "type": "boolean"
        -          },
        -          "symbol": {
        -            "description": "Symbol name to scope the replacement to.",
        -            "type": "string"
        -          }
        -        },
        -        "required": [
        -          "op",
        -          "path",
        -          "symbol",
        -          "old",
        -          "new"
        -        ],
        -        "type": "object"
        -      },
        -      {
        -        "description": "Rewrite a function signature (structured fields and/or full signature text).\n\nPrefer structured `visibility` / `parameters` / `return_type` for multi-language\nedits via [`crate::ast::rewrite::rewrite_function_signature`]. Use\n`new_signature` to replace the entire signature span (any language with\ntree-sitter support). At least one of the structured fields or\n`new_signature` must be set.",
        -        "properties": {
        -          "lang": {
        -            "default": null,
        -            "description": "Language hint (e.g. \"rust\", \"python\"). Overrides extension detection.",
        -            "type": [
        -              "string",
        -              "null"
        -            ]
        -          },
        -          "new_signature": {
        -            "default": null,
        -            "description": "Full replacement signature text (replaces the signature span).\nAlias `to` matches rename/replace agent priors for the new text.",
        -            "type": [
        -              "string",
        -              "null"
        -            ]
        -          },
        -          "old": {
        -            "description": "Function name to rewrite (aliases `name`/`from` for agents).",
        -            "type": "string"
        -          },
        -          "op": {
        -            "const": "ast.rewrite_signature",
        -            "type": "string"
        -          },
        -          "parameters": {
        -            "default": null,
        -            "description": "New parameter list including parens (e.g. `\"(x: i32)\"`).",
        -            "type": [
        -              "string",
        -              "null"
        -            ]
        -          },
        -          "path": {
        -            "description": "Source file containing the function.",
        -            "type": "string"
        -          },
        -          "return_type": {
        -            "default": null,
        -            "description": "New return type using language-native syntax (e.g. `\"-> String\"`).",
        -            "type": [
        -              "string",
        -              "null"
        -            ]
        -          },
        -          "visibility": {
        -            "default": null,
        -            "description": "New visibility (e.g. `\"pub\"`, `\"pub(crate)\"`, or `\"\"` for private).",
        -            "type": [
        -              "string",
        -              "null"
        -            ]
        -          }
        -        },
        -        "required": [
        -          "op",
        -          "path",
        -          "old"
        -        ],
        -        "type": "object"
        -      },
        -      {
        -        "properties": {
        -          "after": {
        -            "default": null,
        -            "description": "Insert after this symbol.",
        -            "type": [
        -              "string",
        -              "null"
        -            ]
        -          },
        -          "before": {
        -            "default": null,
        -            "description": "Insert before this symbol.",
        -            "type": [
        -              "string",
        -              "null"
        -            ]
        -          },
        -          "content": {
        -            "description": "Code to insert.",
        -            "type": "string"
        -          },
        -          "inside": {
        -            "default": null,
        -            "description": "Module/impl/struct to insert into.",
        -            "type": [
        -              "string",
        -              "null"
        -            ]
        -          },
        -          "lang": {
        -            "default": null,
        -            "type": [
        -              "string",
        -              "null"
        -            ]
        -          },
        -          "op": {
        -            "const": "ast.insert",
        -            "type": "string"
        -          },
        -          "path": {
        -            "description": "File to insert code into.",
        -            "type": "string"
        -          },
        -          "position": {
        -            "default": null,
        -            "description": "Position within `inside`: \"start\" or \"end\" (default).",
        -            "type": [
        -              "string",
        -              "null"
        -            ]
        -          }
        -        },
        -        "required": [
        -          "op",
        -          "path",
        -          "content"
        -        ],
        -        "type": "object"
        -      },
        -      {
        -        "properties": {
        -          "lang": {
        -            "default": null,
        -            "type": [
        -              "string",
        -              "null"
        -            ]
        -          },
        -          "lines": {
        -            "default": null,
        -            "description": "Line range to wrap (mutually exclusive with `symbols`).",
        -            "type": [
        -              "string",
        -              "null"
        -            ]
        -          },
        -          "op": {
        -            "const": "ast.wrap",
        -            "type": "string"
        -          },
        -          "path": {
        -            "type": "string"
        -          },
        -          "preamble": {
        -            "default": null,
        -            "description": "Content to insert at the top of the wrapped block.",
        -            "type": [
        -              "string",
        -              "null"
        -            ]
        -          },
        -          "symbols": {
        -            "default": null,
        -            "description": "Symbols to wrap (mutually exclusive with `lines`).",
        -            "items": {
        -              "type": "string"
        -            },
        -            "type": [
        -              "array",
        -              "null"
        -            ]
        -          },
        -          "wrapper": {
        -            "description": "The wrapping construct (e.g. \"mod foo\", \"impl Bar\").",
        -            "type": "string"
        -          }
        -        },
        -        "required": [
        -          "op",
        -          "path",
        -          "wrapper"
        -        ],
        -        "type": "object"
        -      },
        -      {
        -        "properties": {
        -          "add": {
        -            "default": null,
        -            "description": "Import statements to add.",
        -            "items": {
        -              "type": "string"
        -            },
        -            "type": [
        -              "array",
        -              "null"
        -            ]
        -          },
        -          "dedupe": {
        -            "default": false,
        -            "description": "Deduplicate imports.",
        -            "type": "boolean"
        -          },
        -          "lang": {
        -            "default": null,
        -            "type": [
        -              "string",
        -              "null"
        -            ]
        -          },
        -          "op": {
        -            "const": "ast.imports",
        -            "type": "string"
        -          },
        -          "path": {
        -            "type": "string"
        -          },
        -          "remove": {
        -            "default": null,
        -            "description": "Import statements to remove.",
        -            "items": {
        -              "type": "string"
        -            },
        -            "type": [
        -              "array",
        -              "null"
        -            ]
        -          }
        -        },
        -        "required": [
        -          "op",
        -          "path"
        -        ],
        -        "type": "object"
        -      },
        -      {
        -        "properties": {
        -          "inside": {
        -            "default": null,
        -            "description": "Scope to reorder within (module/impl). Default: top-level.",
        -            "type": [
        -              "string",
        -              "null"
        -            ]
        -          },
        -          "lang": {
        -            "default": null,
        -            "type": [
        -              "string",
        -              "null"
        -            ]
        -          },
        -          "op": {
        -            "const": "ast.reorder",
        -            "type": "string"
        -          },
        -          "order": {
        -            "description": "Ordering: \"alphabetical\", \"reverse\", \"kind-first\", or array of names."
        -          },
        -          "path": {
        -            "type": "string"
        -          }
        -        },
        -        "required": [
        -          "op",
        -          "path",
        -          "order"
        -        ],
        -        "type": "object"
        -      },
        -      {
        -        "properties": {
        -          "lang": {
        -            "default": null,
        -            "type": [
        -              "string",
        -              "null"
        -            ]
        -          },
        -          "module": {
        -            "description": "Module name to create or append to.",
        -            "type": "string"
        -          },
        -          "op": {
        -            "const": "ast.group",
        -            "type": "string"
        -          },
        -          "path": {
        -            "type": "string"
        -          },
        -          "position": {
        -            "default": null,
        -            "description": "Where to place new module: \"first-symbol\" (default), \"end\", or \"after:<symbol>\".",
        -            "type": [
        -              "string",
        -              "null"
        -            ]
        -          },
        -          "preamble": {
        -            "default": null,
        -            "description": "Code to insert at the top of the module (e.g., `use super::*;`).",
        -            "type": [
        -              "string",
        -              "null"
        -            ]
        -          },
        -          "symbols": {
        -            "description": "Symbols to move into the module.",
        -            "items": {
        -              "type": "string"
        -            },
        -            "type": "array"
        -          }
        -        },
        -        "required": [
        -          "op",
        -          "path",
        -          "module",
        -          "symbols"
        -        ],
        -        "type": "object"
        -      },
        -      {
        -        "properties": {
        -          "lang": {
        -            "default": null,
        -            "type": [
        -              "string",
        -              "null"
        -            ]
        -          },
        -          "new_module_path": {
        -            "description": "Module path consumers should import from (required with `update_imports`).",
        -            "type": [
        -              "string",
        -              "null"
        -            ]
        -          },
        -          "old_module_path": {
        -            "description": "Module path consumers currently import from (required with `update_imports`).",
        -            "type": [
        -              "string",
        -              "null"
        -            ]
        -          },
        -          "op": {
        -            "const": "ast.move",
        -            "type": "string"
        -          },
        -          "path": {
        -            "description": "Source file.",
        -            "type": "string"
        -          },
        -          "position": {
        -            "default": null,
        -            "description": "Position in target: \"end\" (default), \"start\", \"after:<symbol>\", \"before:<symbol>\".",
        -            "type": [
        -              "string",
        -              "null"
        -            ]
        -          },
        -          "symbols": {
        -            "description": "Symbols to move.",
        -            "items": {
        -              "type": "string"
        -            },
        -            "type": "array"
        -          },
        -          "target": {
        -            "description": "Target file.",
        -            "type": "string"
        -          },
        -          "target_prepend": {
        -            "default": null,
        -            "description": "Content to prepend to target file if it's being created.",
        -            "type": [
        -              "string",
        -              "null"
        -            ]
        -          },
        -          "update_imports": {
        -            "description": "Rewrite consumer `use`/import statements of moved symbols.",
        -            "type": "boolean"
        -          }
        -        },
        -        "required": [
        -          "op",
        -          "path",
        -          "target",
        -          "symbols"
        -        ],
        -        "type": "object"
        -      },
        -      {
        -        "properties": {
        -          "force": {
        -            "default": false,
        -            "description": "Overwrite target if it exists.",
        -            "type": "boolean"
        -          },
        -          "lang": {
        -            "default": null,
        -            "type": [
        -              "string",
        -              "null"
        -            ]
        -          },
        -          "new_module_path": {
        -            "description": "Module path consumers should import from (required with `update_imports`).",
        -            "type": [
        -              "string",
        -              "null"
        -            ]
        -          },
        -          "old_module_path": {
        -            "description": "Module path consumers currently import from (required with `update_imports`).",
        -            "type": [
        -              "string",
        -              "null"
        -            ]
        -          },
        -          "op": {
        -            "const": "ast.extract_to_file",
        -            "type": "string"
        -          },
        -          "prepend": {
        -            "default": null,
        -            "description": "Content to prepend to the target file.",
        -            "type": [
        -              "string",
        -              "null"
        -            ]
        -          },
        -          "replacement": {
        -            "default": null,
        -            "description": "Text to leave in place of the extracted block.",
        -            "type": [
        -              "string",
        -              "null"
        -            ]
        -          },
        -          "source": {
        -            "description": "Source file containing the symbol.",
        -            "type": "string"
        -          },
        -          "symbol": {
        -            "description": "Name of the symbol to extract.",
        -            "type": "string"
        -          },
        -          "target": {
        -            "description": "Destination file path.",
        -            "type": "string"
        -          },
        -          "unwrap": {
        -            "default": null,
        -            "description": "If true (default for modules), remove the wrapper and un-indent.",
        -            "type": [
        -              "boolean",
        -              "null"
        -            ]
        -          },
        -          "update_imports": {
        -            "description": "Rewrite consumer `use`/import statements of the extracted symbol.",
        -            "type": "boolean"
        -          }
        -        },
        -        "required": [
        -          "op",
        -          "source",
        -          "symbol",
        -          "target"
        -        ],
        -        "type": "object"
        -      },
        -      {
        -        "properties": {
        -          "keep_in_source": {
        -            "default": [],
        -            "description": "Symbols to keep in the source file.",
        -            "items": {
        -              "type": "string"
        -            },
        -            "type": "array"
        -          },
        -          "lang": {
        -            "default": null,
        -            "type": [
        -              "string",
        -              "null"
        -            ]
        -          },
        -          "op": {
        -            "const": "ast.split",
        -            "type": "string"
        -          },
        -          "require_exhaustive": {
        -            "default": null,
        -            "description": "Error if any symbol is unaccounted for (default: true).",
        -            "type": [
        -              "boolean",
        -              "null"
        -            ]
        -          },
        -          "source": {
        -            "description": "The file to split.",
        -            "type": "string"
        -          },
        -          "source_prefix": {
        -            "default": null,
        -            "description": "Text to prepend to source after split.",
        -            "type": [
        -              "string",
        -              "null"
        -            ]
        -          },
        -          "source_suffix": {
        -            "default": null,
        -            "description": "Text to append to source after split (e.g., `mod` declarations).",
        -            "type": [
        -              "string",
        -              "null"
        -            ]
        -          },
        -          "targets": {
        -            "description": "Target file specs.",
        -            "items": {
        -              "$ref": "#/$defs/SplitTargetSpec"
        -            },
        -            "type": "array"
        -          }
        -        },
        -        "required": [
        -          "op",
        -          "source",
        -          "targets"
        -        ],
        -        "type": "object"
        -      }
        -    ]
        -  },
        -  "Plan": {
        -    "description": "A transaction plan containing multiple operations to execute atomically.",
        -    "properties": {
        -      "cwd": {
        -        "description": "Optional re-root for relative operation paths and lifecycle steps.\n\nRelative values resolve from the invocation / MCP server workspace root\n(not from the plan file location). Example: `\"fixtures/complex\"` with\nop path `\"config.json\"` targets `fixtures/complex/config.json`.\n\nOn MCP, use a **relative** path that stays inside the server workspace;\nabsolute path strings and `../` escapes are rejected. Do not combine\nwith `for_each` on any surface (glob expansion uses the invocation cwd;\ncombining with `plan.cwd` double-prefixes `{path}`). Use\nworkspace-relative `{path}` templates without `cwd` instead.\nCLI and library callers may use absolute paths when PathGuard policy\nallows them (still without `for_each`).",
        -        "type": [
        -          "string",
        -          "null"
        -        ]
        -      },
        -      "for_each": {
        -        "anyOf": [
        -          {
        -            "$ref": "#/$defs/ForEach"
        -          },
        -          {
        -            "type": "null"
        -          }
        -        ],
        -        "description": "Glob-driven batch: expand operations once per matching file."
        -      },
        -      "format": {
        -        "items": {
        -          "$ref": "#/$defs/FormatStep"
        -        },
        -        "type": [
        -          "array",
        -          "null"
        -        ]
        -      },
        -      "operations": {
        -        "description": "Operations to run. Accepts alias `ops` (common agent shorthand).",
        -        "items": {
        -          "$ref": "#/$defs/Operation"
        -        },
        -        "type": "array"
        -      },
        -      "strict": {
        -        "default": null,
        -        "description": "When omitted from the plan, defaults to strict mode at execution time.",
        -        "type": [
        -          "boolean",
        -          "null"
        -        ]
        -      },
        -      "validate": {
        -        "items": {
        -          "$ref": "#/$defs/ValidationStep"
        -        },
        -        "type": [
        -          "array",
        -          "null"
        -        ]
        -      },
        -      "verify": {
        -        "description": "Pre/post-operation symbol verification checks.",
        -        "items": {
        -          "$ref": "#/$defs/VerifyCheck"
        -        },
        -        "type": [
        -          "array",
        -          "null"
        -        ]
        -      },
        -      "version": {
        -        "default": 1,
        -        "description": "Schema version. Defaults to 1 when omitted.",
        -        "format": "uint32",
        -        "minimum": 0,
        -        "type": "integer"
        -      },
        -      "write_policy": {
        -        "anyOf": [
        -          {
        -            "$ref": "#/$defs/WritePolicyOverride"
        -          },
        -          {
        -            "type": "null"
        -          }
        -        ]
        -      }
        -    },
        -    "required": [
        -      "operations"
        -    ],
        -    "type": "object"
        -  },
        -  "SplitTargetSpec": {
        -    "description": "Target file specification for `ast.split`.",
        -    "properties": {
        -      "path": {
        -        "description": "Target file path.",
        -        "type": "string"
        -      },
        -      "prepend": {
        -        "default": null,
        -        "description": "Content to prepend to this target file.",
        -        "type": [
        -          "string",
        -          "null"
        -        ]
        -      },
        -      "symbols": {
        -        "description": "Symbols to move into this file.",
        -        "items": {
        -          "type": "string"
        -        },
        -        "type": "array"
        -      }
        -    },
        -    "required": [
        -      "path",
        -      "symbols"
        -    ],
        -    "type": "object"
        -  },
        -  "ValidationStep": {
        -    "description": "A validation step to run after applying operations.",
        -    "properties": {
        -      "cmd": {
        -        "type": "string"
        -      },
        -      "required": {
        -        "type": [
        -          "boolean",
        -          "null"
        -        ]
        -      },
        -      "timeout": {
        -        "description": "Timeout in seconds (default: 60).",
        -        "format": "uint64",
        -        "minimum": 0,
        -        "type": [
        -          "integer",
        -          "null"
        -        ]
        -      }
        -    },
        -    "required": [
        -      "cmd"
        -    ],
        -    "type": "object"
        -  },
        -  "VerifyCheck": {
        -    "anyOf": [
        -      {
        -        "description": "`{\"kind\": \"function\", \"attr\": \"test\"}` or `{\"kind\": \"function\"}`",
        -        "properties": {
        -          "attr": {
        -            "default": null,
        -            "type": [
        -              "string",
        -              "null"
        -            ]
        -          },
        -          "kind": {
        -            "type": "string"
        -          }
        -        },
        -        "required": [
        -          "kind"
        -        ],
        -        "type": "object"
        -      },
        -      {
        -        "description": "`{\"check\": \"unique_names\"}` or `{\"check\": \"no_orphans\"}`",
        -        "properties": {
        -          "check": {
        -            "type": "string"
        -          }
        -        },
        -        "required": [
        -          "check"
        -        ],
        -        "type": "object"
        -      }
        -    ],
        -    "description": "A single verification check parsed from `--verify` or plan `verify` field."
        -  },
        -  "WritePolicyOverride": {
        -    "description": "Partially-specified write policy for config files, plans, and overrides.\n\nEach field is optional; only `Some` values override the base [`WritePolicy`].\nUsed by `.patchloom.toml` config, tx plan `write_policy`, and any context\nthat needs to partially override write transformations.",
        -    "properties": {
        -      "collapse_blanks": {
        -        "default": null,
        -        "type": [
        -          "boolean",
        -          "null"
        -        ]
        -      },
        -      "ensure_final_newline": {
        -        "default": null,
        -        "type": [
        -          "boolean",
        -          "null"
        -        ]
        -      },
        -      "normalize_eol": {
        -        "default": null,
        -        "type": [
        -          "string",
        -          "null"
        -        ]
        -      },
        -      "respect_editorconfig": {
        -        "default": null,
        -        "type": [
        -          "boolean",
        -          "null"
        -        ]
        -      },
        -      "trim_trailing_whitespace": {
        -        "default": null,
        -        "type": [
        -          "boolean",
        -          "null"
        -        ]
        -      }
        -    },
        -    "type": "object"
        -  }
        -}
      • addedInput schema / properties / agent_preset
        Added value: +{
        +  "default": false,
        +  "description": "When true, replace ops in this plan use the agent preset (#2614).",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / plan / additionalProperties
        Added value: +true
      • removedInput schema / properties / plan / anyOf
        Removed value: -[
        -  {
        -    "$ref": "#/$defs/Plan"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • changedInput schema / properties / plan / description
        Previous value: -"Full inline plan object (preferred for agents; same schema as CLI tx plans).\nMust contain at minimum `version` and `operations` (alias `ops` also accepted)."New value: +"Inline plan object. Field details for one op come from `operation_schema`.\n`operations` may be sent as `ops`."
      • addedInput schema / properties / plan / properties
        Added value: +{
        +  "operations": {
        +    "items": {
        +      "additionalProperties": true,
        +      "properties": {
        +        "op": {
        +          "type": "string"
        +        }
        +      },
        +      "required": [
        +        "op"
        +      ],
        +      "type": "object"
        +    },
        +    "type": "array"
        +  },
        +  "version": {
        +    "type": "integer"
        +  }
        +}
      • addedInput schema / properties / plan / required
        Added value: +[
        +  "version",
        +  "operations"
        +]
      • addedInput schema / properties / plan / type
        Added value: +[
        +  "object",
        +  "null"
        +]
    • Addedexplain_plan
    • Changedfix_whitespace2 fields changed
      • addedInput schema / properties / agent_preset
        Added value: +{
        +  "default": false,
        +  "description": "When true, replace uses the agent preset: unique, require_change, fuzzy floor 0.90, allow_absent_old false. Off unless set.",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / expected_sha256
        Added value: +{
        +  "description": "SHA-256 hex of the file's current bytes. If it does not match, the tool returns error_kind stale and writes nothing.",
        +  "type": "string"
        +}
    • Changedmd_dedupe_headings2 fields changed
      • addedInput schema / properties / agent_preset
        Added value: +{
        +  "default": false,
        +  "description": "When true, replace uses the agent preset: unique, require_change, fuzzy floor 0.90, allow_absent_old false. Off unless set.",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / expected_sha256
        Added value: +{
        +  "description": "SHA-256 hex of the file's current bytes. If it does not match, the tool returns error_kind stale and writes nothing.",
        +  "type": "string"
        +}
    • Changedmd_insert_after_heading2 fields changed
      • addedInput schema / properties / agent_preset
        Added value: +{
        +  "default": false,
        +  "description": "When true, replace uses the agent preset: unique, require_change, fuzzy floor 0.90, allow_absent_old false. Off unless set.",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / expected_sha256
        Added value: +{
        +  "description": "SHA-256 hex of the file's current bytes. If it does not match, the tool returns error_kind stale and writes nothing.",
        +  "type": "string"
        +}
    • Changedmd_insert_after_section2 fields changed
      • addedInput schema / properties / agent_preset
        Added value: +{
        +  "default": false,
        +  "description": "When true, replace uses the agent preset: unique, require_change, fuzzy floor 0.90, allow_absent_old false. Off unless set.",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / expected_sha256
        Added value: +{
        +  "description": "SHA-256 hex of the file's current bytes. If it does not match, the tool returns error_kind stale and writes nothing.",
        +  "type": "string"
        +}
    • Changedmd_insert_before_heading2 fields changed
      • addedInput schema / properties / agent_preset
        Added value: +{
        +  "default": false,
        +  "description": "When true, replace uses the agent preset: unique, require_change, fuzzy floor 0.90, allow_absent_old false. Off unless set.",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / expected_sha256
        Added value: +{
        +  "description": "SHA-256 hex of the file's current bytes. If it does not match, the tool returns error_kind stale and writes nothing.",
        +  "type": "string"
        +}
    • Changedmd_replace_section2 fields changed
      • addedInput schema / properties / agent_preset
        Added value: +{
        +  "default": false,
        +  "description": "When true, replace uses the agent preset: unique, require_change, fuzzy floor 0.90, allow_absent_old false. Off unless set.",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / expected_sha256
        Added value: +{
        +  "description": "SHA-256 hex of the file's current bytes. If it does not match, the tool returns error_kind stale and writes nothing.",
        +  "type": "string"
        +}
    • Changedmd_table_append2 fields changed
      • addedInput schema / properties / agent_preset
        Added value: +{
        +  "default": false,
        +  "description": "When true, replace uses the agent preset: unique, require_change, fuzzy floor 0.90, allow_absent_old false. Off unless set.",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / expected_sha256
        Added value: +{
        +  "description": "SHA-256 hex of the file's current bytes. If it does not match, the tool returns error_kind stale and writes nothing.",
        +  "type": "string"
        +}
    • Changedmd_upsert_bullet2 fields changed
      • addedInput schema / properties / agent_preset
        Added value: +{
        +  "default": false,
        +  "description": "When true, replace uses the agent preset: unique, require_change, fuzzy floor 0.90, allow_absent_old false. Off unless set.",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / expected_sha256
        Added value: +{
        +  "description": "SHA-256 hex of the file's current bytes. If it does not match, the tool returns error_kind stale and writes nothing.",
        +  "type": "string"
        +}
    • Changedmove_file2 fields changed
      • addedInput schema / properties / agent_preset
        Added value: +{
        +  "default": false,
        +  "description": "When true, replace uses the agent preset: unique, require_change, fuzzy floor 0.90, allow_absent_old false. Off unless set.",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / expected_sha256
        Added value: +{
        +  "description": "SHA-256 hex of the file's current bytes. If it does not match, the tool returns error_kind stale and writes nothing.",
        +  "type": "string"
        +}
    • Addednotebook_edit
    • Addedoperation_schema
    • Changedprepend_file2 fields changed
      • addedInput schema / properties / agent_preset
        Added value: +{
        +  "default": false,
        +  "description": "When true, replace uses the agent preset: unique, require_change, fuzzy floor 0.90, allow_absent_old false. Off unless set.",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / expected_sha256
        Added value: +{
        +  "description": "SHA-256 hex of the file's current bytes. If it does not match, the tool returns error_kind stale and writes nothing.",
        +  "type": "string"
        +}
    • Changedread_file5 fields changed
      • addedInput schema / properties / end_line
        Added value: +{
        +  "description": "1-based inclusive end. Alias of the right side of `lines`.",
        +  "format": "uint64",
        +  "minimum": 0,
        +  "type": [
        +    "integer",
        +    "null"
        +  ]
        +}
      • addedInput schema / properties / limit
        Added value: +{
        +  "description": "How many lines to return, starting at `offset` (or line 1).",
        +  "format": "uint64",
        +  "minimum": 0,
        +  "type": [
        +    "integer",
        +    "null"
        +  ]
        +}
      • changedInput schema / properties / lines / description
        Previous value: -"Optional line range (e.g., \"10:25\")."New value: +"Optional line range (e.g., \"10:25\"). 1-based inclusive."
      • addedInput schema / properties / offset
        Added value: +{
        +  "description": "1-based first line. Same window as Claude Code / Cursor `offset`.",
        +  "format": "uint64",
        +  "minimum": 0,
        +  "type": [
        +    "integer",
        +    "null"
        +  ]
        +}
      • addedInput schema / properties / start_line
        Added value: +{
        +  "description": "1-based inclusive start. Alias of the left side of `lines`.",
        +  "format": "uint64",
        +  "minimum": 0,
        +  "type": [
        +    "integer",
        +    "null"
        +  ]
        +}
    • Changedreplace_text2 fields changed
      • addedInput schema / properties / agent_preset
        Added value: +{
        +  "default": false,
        +  "description": "Apply the agent replace preset for this call (unique, require_change,\nfuzzy floor 0.90, allow_absent_old false). Off unless set (#2614).",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / expected_sha256
        Added value: +{
        +  "default": null,
        +  "description": "SHA-256 hex of the file's current bytes. Mismatch is `error_kind: stale`.",
        +  "type": [
        +    "string",
        +    "null"
        +  ]
        +}
    • Addedtidy_check
    • Addedundo_list
    • Addedundo_restore
  2. 58 tool updatesv0.32.0
    • First observedappend_file
    • First observedapply_fragment
    • First observedapply_patch
    • First observedast_deps
    • First observedast_diff
    • First observedast_extract_to_file
    • First observedast_group
    • First observedast_impact
    • First observedast_imports
    • First observedast_insert
    • First observedast_list
    • First observedast_map
    • First observedast_move
    • First observedast_read
    • First observedast_refs
    • First observedast_rename
    • First observedast_reorder
    • First observedast_replace
    • First observedast_rewrite_signature
    • First observedast_search
    • First observedast_split
    • First observedast_validate
    • First observedast_wrap
    • First observedbatch_replace
    • First observedbatch_tidy
    • First observedcreate_file
    • First observeddelete_file
    • First observeddoc_append
    • First observeddoc_delete
    • First observeddoc_delete_where
    • First observeddoc_diff
    • First observeddoc_ensure
    • First observeddoc_get
    • First observeddoc_merge
    • First observeddoc_move
    • First observeddoc_prepend
    • First observeddoc_query
    • First observeddoc_set
    • First observeddoc_update
    • First observedexecute_plan
    • First observedfix_whitespace
    • First observedgit_status
    • First observedlist_files
    • First observedmd_dedupe_headings
    • First observedmd_insert_after_heading
    • First observedmd_insert_after_section
    • First observedmd_insert_before_heading
    • First observedmd_lint
    • First observedmd_move_section
    • First observedmd_replace_section
    • First observedmd_table_append
    • First observedmd_upsert_bullet
    • First observedmove_file
    • First observedprepend_file
    • First observedread_file
    • First observedreplace_text
    • First observedsearch_files
    • First observedserver_info

TDQS

B3.4/5.0

Scored across 66 tools

Disambiguation4/5

Tools are largely separated by domain prefixes (ast_, doc_, md_, file/apply/undo), and descriptions explicitly scope overlapping-looking operations such as doc_set vs doc_update and replace_text vs ast_replace. Still, the large doc/markdown/AST clusters contain several near-neighbors that require careful reading to select correctly.

Naming Consistency4/5

Almost all tools use snake_case with a consistent domain-prefix convention (ast_, md_, doc_) plus verb_noun file/search/plan names. A few names are noun-like (server_info, operation_schema, git_status) rather than verb_noun, but the overall pattern is predictable.

Tool Count2/5

66 tools is far beyond the recommended 3-15 range and exceeds the 25+ 'too many' threshold; the broad patch/edit domain justifies more than a small set, but this volume imposes high selection overhead on an agent. The surface would benefit from consolidation or tiered exposure.

Completeness4/5

Coverage is extensive across file editing, AST manipulation, markdown, structured documents, search, planning, and undo, with CRUD-style coverage for most resources. Minor gaps remain, such as markdown section/table deletion, notebook read/create, and directory operations, but core workflows are not dead-ended.

Maintenance

ActivityActive
ResponsivenessUnresponsive

Related MCP Connectors

Related MCP Servers

  • A
    license
    B
    quality
    D
    maintenance
    Advanced code search and transformation MCP server for AI assistants. Combines ugrep's speed with intelligent replace capabilities, dry-run previews, and language-aware refactoring across 11 tools.
    1
    10
    MIT
  • A
    license
    A
    quality
    A
    maintenance
    A robust, language-agnostic Model Context Protocol (MCP) server that provides AI coding agents with the ability to edit files surgically via Abstract Syntax Trees (AST) instead of relying on token-heavy, brittle search-and-replace or diff operations.
    28
    10
    MIT
  • A
    license
    A
    quality
    B
    maintenance
    AST-targeted code editing MCP server with 28 surgical tools for structural edits across 11 languages. Built on tree-sitter, replaces brittle search/replace with byte-correct edits keyed by symbol names.
    2
    28
    MIT