ast-editor
This server provides AST-aware tools for surgically reading, editing, navigating, and configuring source and config files instead of brittle search-and-replace.
Inspect files with
list_symbols,read_imports, and targetedread_symbolat full, interface, or signature depth.Find identifier occurrences within a file using
find_references.Replace whole functions, function bodies, signatures, or specific snippets inside a function body.
Insert or delete snippets inside function bodies, including anchored insertions after or before existing text.
Add methods, fields, parameters, top-level declarations, and sibling symbols.
Remove parameters, symbols, and imports; manage named imports by adding or removing individual names.
Edit leading comments and Python docstrings without rewriting surrounding code.
Edit JSON/YAML/TOML config and dict/list/object literals by adding, replacing, deleting keys, or appending/removing array items.
Preserve code formatting, decorators, comments, line endings, BOMs, and trailing blank lines where applicable.
Refuse syntax-breaking edits via re-parsing, while allowing work on files that already contain syntax errors.
Supports Python, JavaScript, TypeScript, C, C++, Ruby, Go, Java, JSON, YAML, and TOML with language-aware behavior.
Provides tools for surgically editing C++ source files via AST, including structural edits to functions, classes, methods, fields, and imports, with support for comments and annotations.
Provides tools for surgically editing JavaScript/JSX source files via AST, including structural edits to functions, classes, methods, fields, and imports, with support for comments.
Provides tools for surgically editing Python source files via AST, including structural edits to functions, classes, methods, fields, imports, docstrings, and module-level dict/list literals.
Provides tools for surgically editing Ruby source files via AST, including structural edits to classes, modules, methods, singleton methods, and imports.
Provides tools for surgically editing TOML configuration files via AST, including adding, deleting, and replacing keys and values, as well as appending to arrays.
Provides tools for surgically editing TypeScript/TSX source files via AST, including structural edits to functions, classes, interfaces, methods, fields, and imports, with support for comments.
Provides tools for surgically editing YAML files via AST, including adding, deleting, and replacing keys and values, as well as appending to sequences.
AST Code Editor MCP Server
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.
Why AST Edits?
Every non-AST edit format — search/replace, unified diff, whole-file rewrite — requires the model to copy text perfectly from a file it saw once. One whitespace mismatch on a 4,000-line file and the edit fails. AST edits sidestep the problem entirely: the model names the target (e.g., LRUCache.get) and provides the new code; the parser figures out where it lives.
Geometric AGI benchmarked every major format across 4 models and 29 edit tasks. AST edits were the only format to hit 100% correctness on 3 of 4 models, with 18x fewer output tokens than whole-file rewrite, and zero format failures. Full methodology and results: AST Edits: The Code Editing Format Nobody Uses.
Credits
This MCP server was inspired by research from Jack Foxabbott and the team at Geometric AGI. Their full findings, benchmark suite, and data are available here:
Jack Foxabbott's original post (LinkedIn)
GeometricAGI/blog (Benchmark code & data)
Related MCP server: code-index-mcp
Estimated Token Savings
Per-edit output token savings versus other common edit formats:
Edit size | File size | vs whole-file rewrite | vs unified diff | vs search/replace |
1-line tweak | 100 LoC | 3–5x | ~1.5x | ~1.5x |
Function body rewrite | 500 LoC | 8–12x | 2–3x | 2–3x |
Function body rewrite | 4,000 LoC | 15–20x | 3–5x | 3–5x |
Add 2 lines to a function | any size | ~20x (via | 5–10x | 3–5x |
Per-read input token savings versus reading the entire file:
Read task | File size | AST reader tool | vs full file read |
One function's source | 500 LoC |
| ~20x fewer tokens |
One function's source | 2,000 LoC |
| ~50-100x fewer tokens |
Class API (10 methods, no bodies) | 500 LoC |
| ~10x fewer tokens |
Import block only | any size |
| ~20-50x fewer tokens |
Structural overview (names + line numbers) | any size |
| ~15-30x fewer tokens |
One function's signature | any size |
| ~50-200x fewer tokens |
For daily agent users, a realistic 40-60% reduction in total tokens per session is achievable, on average (combining output savings from surgical edits with input savings from targeted reads).
The savings come from four compounding effects:
Output tokens: Using
insert_in_body(at="top"/at="bottom", or anchored withafter=/before=) for small additions instead of rewriting whole function bodiesInput tokens: Using
read_symbol(depth="full"/"interface") /read_importsto read only what's needed instead of entire files (~10-20x fewer input tokens per read)Discovery:
list_symbols/read_symbol(depth="signature")instead of reading whole filesZero format failures: AST edits never fail on whitespace drift, eliminating retry loops that plague other formats.
Supported Languages & Capabilities
Language | Extensions | Structural edits | Comments | Docstrings | Notes |
Python |
| ✅ | ✅ | ✅ function/class | Decorators preserved. Nested classes (decorated ones too) are listed with their members ( |
JavaScript |
| ✅ | ✅ | — | Exported declarations ( |
TypeScript |
| ✅ | ✅ | — | Exports, generators and functions bound to names as for JavaScript. Abstract classes ( |
C |
| ✅ | ✅ | — |
|
C++ |
| ✅ | ✅ | — | Supports |
Ruby |
| ✅ | ✅ | — | Classes, modules, instance methods, |
Go |
| ✅ | ✅ | — |
|
Java |
| ✅ | ✅ | — |
|
JSON |
| ✅ (keys, values, arrays) | — (no comment syntax) | — | Numbers with a |
YAML |
| ✅ (keys, values, sequences) | ✅ | — | Block and flow sequences supported. Keys inside flow mappings are addressable by path ( |
TOML |
| ✅ (keys, values, arrays, tables) | ✅ | — |
|
Cross-cutting features:
Decorated functions and classes (Python and JS/TS
@decorator, Java annotations): decorators are part of the symbol. They are preserved on body edits;read_symbol,replace_functionanddelete_symbolinclude them; a leading comment belongs above the first of them (edit_leading_commentputs it there and finds an existing one there), andinsert_sibling(position="before")goes above them and that comment, so the comment stays on the symbol it documents. This holds for TypeScript methods too, whose decorators the grammar places beside the method in the class body, for decorated Python classes, for a C++ template'stemplate <...>header and for a Ruby Sorbetsig.replace_signaturekeeps them as written unless the new signature includes its own, which then replace them.Layout-aware
add_method/add_field: the new member is indented like the class's existing members (falling back to the file's indent unit, then the language default: 4 spaces for Python and Java, a tab for Go, 2 spaces otherwise), keeping the content's relative indentation; in a class indented with tabs that indentation is written in tabs too (one per indentation step of the content), so a snippet written with spaces fits a tab-indented file. The lines that start inside a multi-line string literal of the content (a triple-quoted string, template literal, heredoc, raw string, C string continued with\) or a Ruby embedded document (=begin...=end, at column 0) keep their text, here and in every tool that re-indents content (replace_function,replace_function_body,insert_in_body(at=...),insert_sibling,edit_leading_comment); a Python docstring, a Ruby<<~heredoc and a Java text block, whose indentation the language strips, move with the code instead, every line by the same amount. A method follows the last member after one blank line, or none when the class's methods have no blank lines between them (a C++ member template counts as a method; TS interface members stay one per line) or the last member is a C++ access label (public:), and one-line content after stacked one-line members (fields) is stacked with them. In a C++ class whose last method is followed by an access label (public:,protected:,private:), the new method goes right after that method, spaced as methods are, so it gets the same access; a comment after that method on its line stays with it, a method inside an#if/#ifdefblock (either branch) counts as the last method (the new one goes after the#endif), and a label moved off a method's line is indented like the class's other labels, or at the class's indentation. A C++ class with no label after its last method, or with no methods, gets the new method after its last member. Content inread_symbol's shape copied from another class (its first line without indentation, the later lines at the indentation they had there) is indented as a whole, a Python def without decorators only when it was read at the indentation of this class's members. A field goes before the first member (after a Python class docstring, and below the access label a C++ class body opens with, so it gets that section's access), with a blank line after it when that member is a method (a C++ member template counts), and a comment after the{on its line (class K { // NOLINT) stays there. In a Java enum both go after the constants, and a;is added after them when they have none. No blank line is added before the closing brace, and a braced body on one line (class K {},class K { a() {} }, Gostruct{ A int }) is opened up over several lines, its existing members on a line of their own. A Python or Ruby class written on one line (class K: pass) is refused. Both tools look only at containers, so a name a struct or interface shares with a function (struct statandint stat(...)) is the struct, a typedef of a struct declared apart (typedef struct Node Node;) is that struct, and a function target is refused (useinsert_in_body).Layout-aware
add_key: in JSON objects, Python dicts, JS/TS object literals, YAML flow mappings and TOML inline tables the new entry follows the container's layout (one key per line at the existing indentation, inline objects stay inline, a trailing comma is kept, and a comment on the last entry's line stays there); an empty JS/TS or YAML{}becomes{ key: value }(TOML:{ key = value }). A YAML key with no value gets a nested block mapping one indentation level deeper (inside a flow mapping, an inlineparent: { key: value }). YAML and TOML keys are quoted only when they need it:my keyanda.bstay plain in YAML, whilea:b,yes,123or a leading-/#/&get quotes (in the quote style most of the file uses); in TOML anything but a bare key (letters, digits,_,-) is quoted, and dots separate the parts of a dotted key, sob.caddscunderband a name with a dot in it must be passed quoted ('"example.com"'). A JSON or YAML key passed already in quotes is used as given. A key the container already has is refused with a pointer toreplace_value, for every format, naming a target that works (quoted where the key has a dot, inside flow mappings and inline tables too).Layout-aware
append_to_array: JSON arrays, TOML arrays, YAML flow sequences and Python lists keep their layout: an inline array stays inline ([1, 2]becomes[1, 2, 3],[]becomes[3]), an array with one element per line gets a new line at the elements' indentation (also one aligned under its[whose]closes the last line), a trailing comma is kept (the new element gets one too), and comments are not elements: one on the last element's line stays there, after the comma (2, # two), and a value that ends with a comment gets its comma before it (3, # new). A Python list whose[and]are on lines of their own with nothing between them gets the value on a line of its own, with a comma. A YAML block sequence gets a new- valueitem.Config paths from the top level: a dotted config target is followed from the top of the file, one key per segment:
a.bis keybunder the top-level keya, never ana.bnested deeper (such asx.a.b), and in TOML a plainversionis a top-level key, not one inside a[table](useproject.version). One path syntax covers JSON, YAML and TOML and every config tool (read_symbol,replace_value,add_key'sparent_target,delete_key,append_to_array,remove_from_arrayandedit_leading_comment): a segment in double quotes is one key taken literally, dots included, its escapes resolved as in a JSON string ("editor.fontSize",a."b.c".d), and in TOML single quotes work too (a.'b.c'), as in a TOML dotted key, whose syntax TOML paths share. Keys compare by the names they spell, so"a.b"findsa.b: 1,'a.b': 1and"a.b": 1in YAML, and[x.'y.z']and[ x . "y.z" ]are both TOML tablex."y.z". Keys inside YAML flow mappings and TOML inline tables are part of the path. Elements of arrays are not addressable by path (a.0is a key named0).Byte-correct slicing: multi-byte characters (emoji,
═,→) handled safely in source text.Import placement:
add_importskips exact duplicates. A new import goes into the group it belongs with, a group being a run of imports, includes or requires with no blank line or other code between them (comments may be; a conditional of includes counts as one include, a CommonJSrequireas an import). The group is picked by language. Python: a group holding imports of the same top-level package, else the standard-library group for a standard-library module and the group of other modules for others, relative imports with relative imports. C/C++:<...>with<...>,"..."with"...", never a group of only the file's own header ("foo.h"infoo.cpp). Go: standard-library paths (no dot in the first path element) with standard-library paths, others with others, never with cgo'simport "C". JS/TS: relative paths (./,../) with relative paths, packages with packages, arequirewith requires. Java: static with static. Ruby:require_relativewithrequire_relative. When several groups fit, the one with an import sharing the longest leading path with the new one wins (package parts, directories:from app.y import zgoes withfrom app import x,#include <sys/types.h>with<sys/stat.h>), else the first; when none fits, the import goes after the file's last import. In a group that is already sorted it goes at its sorted place, else after the group's last import. Python sorts as isort and ruff do: module names without case, numbers in numeric order,import xlines beforefrom x importlines in a group that orders them that way, else both together. The other languages sort by the path or module text (C/C++ includes as written, with their brackets or quotes). The import goes above the next import and the comment lines right above it, but below a comment above the group's first import, which heads the group; a comment that applies to the next line stays on its import even when the new import sorts first (@ts-ignore,@ts-expect-error, eslint or tslintdisable-next-line, pylintdisable-next,biome-ignore,deno-lint-ignore,prettier-ignore,NOLINTNEXTLINE, Flow suppressions, istanbul, c8 or v8ignore next, Go//nolintand//lint:ignore,noinspection). The blank lines between groups stay as they are. Pythonfrom __future__imports stay first: a new one goes after the existing ones, or before the file's first import, and other imports go after them; afrom __future__import that its group would place after code goes right after the module docstring, before any other statement, with a blank line on each side. Go: inside animport ( ... )block the same rules apply to the block's blank-line groups of specs, an alias sorting by its path ("io"goes between"fmt"and"os"); a block written on one line (import ("fmt"; "os"),import ()) takes the spec inline at its sorted place; without a block, a spec given without its keyword ("fmt",f "path/filepath") is written asimport "fmt"; and nothing goes betweenimport "C"and its cgo preamble comment (the new import goes afterimport "C"). A file's first import goes after its preamble (a package clause,#!and encoding or magic comments, the module docstring,'use strict'and other directives, TS///lines,#pragma once, an include guard's#define, and a header comment set off by a blank line), with a blank line above it and one below it (two before a Python def or class).Doc-comment-aware deletion:
delete_symbolby default removes the contiguous leading comment block above the symbol (Godoc, Javadoc,#///comment runs) so docs don't become orphaned. Opt out withinclude_leading_comments=False. The block ends at a blank line and at a comment line indented deeper than the symbol, which belongs to the code above it (# end of funder f's last line, a commented-out YAML list item), for this and every tool that finds a leading comment:insert_sibling(position="before")goes below such a comment, andedit_leading_commentneither removes nor replaces it. Such comment lines right below a symbol's last line belong to it:delete_symbolremoves them with it andinsert_sibling(position="after")goes below them (read_symbolandreplace_functionleave them out). A Ruby=begin...=enddocument directly above a symbol is its leading comment. Only real comments count, for this and every other tool that finds a leading comment: a line that starts with#or//inside a multi-line string, template literal or YAML block scalar is text. A#!line and the encoding or magic comments after it (# -*- coding: utf-8 -*-,# frozen_string_literal: true) at the top of a Python or Ruby file are never taken for a symbol's comment, by this or any other tool.Layout-aware deletion: the blank lines that separated a deleted symbol go with it, so the rest keeps the file's spacing: deleting the first symbol of a file or class body leaves no blank lines at the top or after the
{, deleting the last one leaves none before the closing brace (and the next top-level symbol keeps its own separation, such as Python's two blank lines), and between the two symbols that remain only the wider of the two gaps stays. Only empty lines and lines of spaces and tabs are blank: a form feed line (a Python page break) next to the symbol stays. A symbol that shares a line with other code (class A { a() {} b() {} },x = 1; y = 2) is cut out of that line instead, with the;or,that ends it (the last entry of a one-line literal takes the one before it:{ a: 1, b: 2 }minusbis{ a: 1 }) and a comment after it at the end of the line; the spaces that were before it stay between the code on both sides.replace_functionlikewise replaces only such a symbol's own text, and refuses content that ends with a#or//comment when code follows the symbol on its line.Syntax-checked saves: before anything is written, the edited file is re-parsed with its tree-sitter grammar. An edit that would introduce a syntax error into a file that parsed cleanly is refused with the error's line and column (e.g.
Edit refused: the result would have a syntax error at line 11, column 2 (missing '}')), and the file is left unchanged. Files that already had syntax errors are not guarded, so you can keep working on them. For.pyfiles Python's own parser (that of the interpreter running the server) decides: it catches the indentation errors tree-sitter lets through and accepts newer syntax the grammar does not know (PEP 696 type parameter defaults). For.jsonfiles thejsonmodule overrules the grammar wherever it would reject valid JSON, and comments in JSONC files stay allowed; exponents written with a+(1e+2), which tree-sitter-json cannot parse, are masked before parsing, so files that use them are checked like any other. Other languages have no second parser, so valid code using syntax the grammar does not support (very new language features, macro-heavy C/C++) can be refused: if you are sure the code is valid, make that edit with your normal edit tool.Line endings and byte order marks preserved: CRLF files stay CRLF and LF files stay LF, whichever tool makes the edit, and blank lines at the end of a file are kept as they were (deleting the last symbol does not leave extra ones behind); a file whose last line has no line break keeps it that way. A UTF-8 byte order mark stays at the start of the file, whatever the edit adds or removes at the top; it never shows up in tool output, and content that starts the file with one leaves a single mark. Files that are not UTF-8 (UTF-16, UTF-32, Latin-1), also UTF-16 or UTF-32 without a byte order mark and files with NUL bytes, are refused with a message saying so, and left unchanged. Write content, snippets and anchors with
\nline breaks: inserted text is converted to the file's style, and a\nin a snippet or anchor matches a CRLF line break. Content is split into lines on\n(or CRLF) only, so a form feed, vertical tab, U+0085, U+2028 or U+2029 inside a string literal or comment stays where it was written. Only spaces and tabs count as indentation, so when content is re-indented a form feed at the start of a line (a Python page break,\fdef g():) or a U+2028 starting a line inside a string stays, and a form feed before the target's owndefis not copied onto the new lines. In a file that mixes CRLF and LF, every line the edit does not rewrite keeps its own ending (the lines next to the edit too, though they read like lines it removed or added); a line it writes takes the ending of the lines it replaces when they agree, else of the lines on both sides when they agree, else the file's most common one.Body snippets and anchors (
replace_in_body,delete_in_body,insert_in_body(after=…, before=…)): a snippet matches its exact text (\nmatching CRLF) where it neither starts nor ends inside a token of code, an identifier, number, keyword or operator:x = 1is not found inmax = 10, nor= 1ina == 1,elin$elorfooin Rubyfoo?; inside a comment or string (not in an interpolation's code) it may start or end between any two words, and it may end at a Python backslash continuation. Without an exact match, its lines match whole lines of the body with one indentation added to or taken from each of them, so a block copied at column 0 or deeper than in the file is found: blank lines match blank lines, spaces and tabs at line ends do not count, tabs and spaces differ, and a snippet that starts or ends in the middle of a line must match exactly. The text of a multi-line string is never shifted: a line that starts inside one is matched only as written in the file (Python docstrings, Ruby<<~heredocs and Java text blocks, which move with the code, aside). An exact match wins, except that when every exact match is inside a string or comment, shifted matches in other places count too. The match must be unique: two or more places are refused with their line numbers (Snippet matches 2 places in body of 'f' (lines 2, 4)), and text found only inside longer tokens is refused saying so. A deletion that leaves its lines without code takes the whole lines, indentation and line break included; a comment after the deleted code on its last line stays, at the line's indentation; a Python body is never left without a statement (replace the snippet withpass). New text goes in indented as the snippet matched: moved with a shifted match's lines; after an exact one-line snippet that left out its line's indentation (or starts mid-line), its later lines given that indentation unless they are that deep already; after an exact snippet of several lines, or when already at the file's indentation there, as written; in Python, when one reading of the indentation does not parse and the other does, the other is taken.insert_in_bodyputs new text on lines of its own when the anchor ends its line (after) or starts it (before), indented like the anchor (new text at column 0 beside an anchor written with its indentation goes at the anchor's, and text inread_symbol's shape goes in as written), and inside the block that anafteranchor's line opens (if (x) {,if x:); in the middle of a line, or where the new line would start in the text of a string or heredoc (not a docstring,<<~heredoc or Java text block, whose lines are indented like code), it is placed byte for byte. Lines of new text that go into a string of the file keep their text.Tab-indented code: every tool that writes source content over several lines (
replace_function,replace_function_body,replace_in_body,insert_in_body,insert_sibling,add_top_level,add_method,add_field) writes the content's indentation steps in tabs where the file indents with tabs there: the place's indentation has a tab, or, at column 0, most of the indented lines of the code it replaces or goes beside start with one (the text of its strings and lines aligned under a bracket aside), or, with no such lines, the file is Go or mostly tab-indented. Each step of the content's own indentation becomes one tab; the text of multi-line strings, Ruby=begindocuments, and the spaces that align a block comment's lines or a line continued inside a(or[stay as written. Config files are never converted.
Language-specific design decisions
A few tools have language-specific semantics where multiple reasonable interpretations exist. The chosen behavior is documented here for transparency:
add_field (Ruby and Go) — option (a): literal text passthrough
Ruby:
add_field("LRUCache", " attr_accessor :capacity")inserts the literal string at the top of the class body. The tool does not auto-wrap bare names inattr_accessor— you provide the exact text you want (whether that'sattr_accessor,attr_reader,@instance_var = nilininitialize, orCLASS_CONST = 42).Go:
add_field("Cache", "\tversion int")inserts the literal string inside thestruct { ... }body. The tool does not infer types from bare names — you provide the full Go field declaration.Rationale: consistent with how
add_fieldworks for other languages (Python, JS/TS, C++) where the caller provides the full source text. The alternative option (b) — auto-wrapping (e.g.attr_accessor :foofrom the namefoo) — would be more magical but harder to use for edge cases (typed fields, readonly fields, field with default value, etc.).
add_method (Go) — option (a): top-level sibling insertion
add_method("Cache", "func (c *Cache) Has(key string) bool { ... }")locates thetype Cache struct { ... }declaration and inserts the new method immediately after it, at the top level (not inside the struct's braces), indented with tabs and with a blank line on each side.Rationale: Go methods are lexically top-level, not nested inside their receiver type — this matches how Go code is actually written. The alternative option (b) — refusing because "Go methods aren't inside structs" — would be pedantically correct but force callers to use
insert_sibling("Cache", content, position="after")instead, which loses the semantic signal that this is a method addition.
Tools Exposed
All tools require file_path to be an absolute path to an existing file.
Code editing — structural (Python, JS, TS, C, C++, Ruby, Go, Java)
Tool | Parameters | Description |
|
| Replace a full function definition (signature + body + decorators, and a JS/TS |
|
| Replace only the body of a function, preserving signature and decorators. A body written on one line with its signature or braces ( |
|
| Replace only the signature, preserving the body. |
|
| Replace a snippet inside a function body, scoped to the target's body: its exact text at token boundaries, else its whole lines with their indentation shifted, matching exactly one place (see Body snippets and anchors above). |
|
| Delete a snippet inside a function body, matched as |
|
| Insert a snippet inside a function body. Pass exactly ONE of: |
|
| Insert top-level content. |
|
| Add a method at the end of a class body (in a C++ class, right after the last method when an access label follows it), indented like the class's members and separated as its methods are (see Layout-aware |
|
| Add a field/attribute/member at the top of a class body (after a Python class docstring or a Java enum's constants, below the access label a C++ class body opens with), indented like the class's members. |
|
| Insert content as a sibling of a named symbol. |
|
| Delete a function or class definition block (including decorators, a JS/TS |
Parameters & signatures
Tool | Parameters | Description |
|
| Add a parameter to a function signature ( |
|
| Remove a parameter by name. One on a line of its own goes with that line and the comment at its end; comments on other lines stay (one after the parameter before it too), a last parameter with no comma after it takes the comma before it (except in Go before a line break, which needs it), and removing the only parameter leaves |
Imports & includes
Tool | Parameters | Description |
|
| Add an |
|
| Remove a matching import line, compared after stripping surrounding whitespace: pass the exact line. |
|
| Add one name to an existing named-import statement: |
|
| Remove one name from a multi-name named-import statement (Python and JS/TS). If the last named import is removed and no default/namespace binding remains, the whole line is removed; removing the last name beside a default binding ( |
Comments & docstrings
Tool | Parameters | Description |
|
| Edit the contiguous leading-comment block above a named symbol, which is above its decorators/annotations, a JS/TS |
|
| Replace or insert a Python function/class docstring, or the module's for |
Dict/list editing (JSON, YAML, TOML, Python module-level dict/list literals, AND JS/TS object literals)
Values (content, value) are literal source text in the file's own syntax ('"2.0.0"', 42): quote strings where the format requires it.
Tool | Parameters | Description |
|
| Replace the value of an existing key. Targets as for |
|
| Add a key-value pair to a dict/object/mapping/table. For config, |
|
| Delete a key-value pair. Targets: JSON/YAML/TOML dotted path from the top level ( |
|
| Append a literal value to a list/array/sequence. For Python, |
|
| Remove the first matching element from a list/array/sequence. |
Navigation & reading (read-only)
Tool | Parameters | Description |
|
| Formatted outline of all top-level functions, classes, methods and data with line numbers, one |
|
| Syntactic search for all occurrences of an identifier (no scope awareness, so same-named unrelated identifiers show up too), matched per identifier rather than as a dotted path, returned as |
|
| Return source text of a single named symbol. |
|
| Return all import/include statements in the file. |
Target format: Use the exact function name (e.g., get) or dotted Class.method path (e.g., LRUCache.get). In C, C++ and Java an overload takes its parameter types (A.m(int, String), A.m(), C f(void) being f()), a C++ definition outside its class its qualified name (A::f), and a name that a field shares with methods targets the field (the method is A.x()). A C/C++ tag or TS type alias or interface that shares its name with another symbol takes its keyword (struct stat, union u, class C, type User, interface Props), in front of a dotted path (type N.User). JS/TS exported declarations are targeted by their own names (export function add is add); an anonymous export default function/class is default (and its methods default.run), and const f = () => {...} is f. Decorated functions are fully supported — decorators are preserved when replacing bodies or signatures, and included when deleting or replacing the full function.
Tip: Call list_symbols first to discover exact target names before editing. This avoids guessing and makes subsequent edits much more reliable.
Which tool should I use?
A decision guide grouped by intent. Start at the top and pick the narrowest match.
Discovering what's in a file (do this first)
Don't know what symbols exist? →
list_symbolsNeed one specific function's full source? →
read_symbol(depth="full", the default — 10-20x cheaper than reading the whole file)Need a class's public API (methods + fields, no bodies)? →
read_symbol(target, depth="interface")Need just a function's signature? →
read_symbol(target, depth="signature")Need to see a file's imports/dependencies? →
read_importsWhere is a symbol used? →
find_references
Dotted targets descend into closures: Go stdioCmd.RunE (func_literal in struct field), TS app.handler (arrow function in object literal).
Adding new content
Intent | Tool |
New top-level function, class, constant, or type alias |
|
New method in an existing class |
|
New field/attribute/member in a class |
|
New content before or after a top-level symbol |
|
New lines at the top of an existing function body |
|
New lines at the bottom of an existing function body |
|
New lines at a specific spot inside a function body (anchored to existing text) |
|
New parameter on an existing function |
|
New import or |
|
New name in an existing |
|
New comment above a symbol |
|
New Python docstring on a function/class |
|
New key in a dict/object/mapping/table (any lang) |
|
New item in a list/array/sequence (any lang) |
|
Modifying existing content
Intent | Tool |
Rewrite the full function (signature + body) |
|
Rewrite only the body, keep the signature |
|
Change one statement/block inside a large body |
|
Change only the signature, keep the body |
|
Change only the leading comment above a symbol |
|
Change only the Python docstring |
|
Change the value of an existing key (config, Python dict, JS/TS object) |
|
Removing content
Intent | Tool |
Remove a function, method, or class |
|
Remove one statement/line inside a function body (a route mount, a middleware call, a key of an inline object-literal argument) |
|
Remove a parameter from a function |
|
Remove an import or |
|
Remove one name from a multi-name named-import (Python or JS/TS) |
|
Remove a leading comment above a symbol |
|
Remove a key from a dict / config / JS-TS object literal |
|
Remove an item from a list/array |
|
Anti-patterns to avoid
Don't use
replace_functionorreplace_function_bodyto change a few lines — usereplace_in_body(scoped snippet match) orinsert_in_body(at="top" \| "bottom")for appending/prepending. Rewriting the whole function is wasteful and error-prone.Don't use
replace_signatureto add or remove one parameter — useadd_parameter/remove_parameter.Don't use
replace_valueto add a new key — useadd_key.replace_valueonly updates existing keys, andadd_keyrefuses a key that already exists.Don't use
add_importto add a name to an existingfrom X import …or named import — useadd_import_name.Don't guess at target names. Call
list_symbolsfirst. Names are case-sensitive and must match exactly.
Escape hatches
Deleting several related symbols? Call
delete_symbolonce per target. There is nodelete_grouptool: the extra calls cost less than a grouped primitive would.Editing a sub-expression inside a method chain (dropping
.references(...)frominteger("x").notNull().references(...))? Usereplace_in_bodywith the literal snippet when it is unique; for arbitrary expression surgery use your normal edit tool, since ast-editor does no pattern matching on expression trees.Rewriting a whole file whose structure changes substantially? Use your normal write tool.
Valid code refused by the syntax check (very new language features, macro-heavy C/C++)? Make that edit with your normal edit tool.
Prerequisites
This MCP server uses uv to manage its Python environment and dependencies automatically. Install uv if you don't have it already:
macOS / Linux:
curl -LsSf https://astral.sh/uv/install.sh | shWindows (PowerShell):
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"Homebrew (macOS):
brew install uvpip (any platform):
pip install uvVerify the installation:
uv --versionFor more options (Docker, Cargo, WinGet, etc.), see the official uv installation docs.
uv 0.9.17 or newer is required. This server's pyproject.toml sets a 7-day dependency cooldown ([tool.uv] exclude-newer = "7 days"). Older uv versions can't parse that relative duration. They print a warning and ignore the setting. A plain uv sync or uv run, including the uv --directory … run launch commands below, then discards the committed uv.lock, re-resolves to the newest compatible versions (even ones published in the last 7 days), and rewrites the file. Upgrade with uv self update, brew upgrade uv, or pip install -U uv, depending on how you installed it. Upgrading doesn't undo an earlier rewrite: restore the original uv.lock with git checkout HEAD -- uv.lock in this folder, or copy it again from the archive you downloaded.
The server depends on mcp, tree-sitter, and a tree-sitter grammar package for each supported language. uv handles all of these automatically on first run.
Installation
Note: Replace
/absolute/path/to/ast-editorbelow with the absolute path to theast-editorfolder on your machine (the folder that contains itspyproject.toml).
Method 1: CLI Configuration (Claude Code, Codex, Gemini)
If your agent supports adding servers via CLI, run the following:
--scope user installs the server globally so it's available in every project on your machine. Drop it if you only want the server active in the current project.
# Claude Code / Codex
[claude|codex] mcp add ast-editor --scope user -- uv --directory /absolute/path/to/ast-editor run ast-editor-mcp
# Gemini CLI
gemini mcp add --transport stdio --scope user ast-editor -- uv --directory /absolute/path/to/ast-editor run ast-editor-mcpMethod 2: JSON Configuration
For tools that use a mcp_config.json or settings.json file, add the following block.
Important: Use the absolute path to
uvfor"command", not just"uv". GUI-based MCP clients (Claude Desktop, Cursor) don't always inherit your shellPATH, so a bare"uv"will fail with a "command not found" error. Get your absolute path with:which uv # e.g. /Users/you/.local/bin/uv or /opt/homebrew/bin/uv
{
"mcpServers": {
"ast-editor": {
"command": "/absolute/path/to/uv",
"args": [
"--directory",
"/absolute/path/to/ast-editor",
"run",
"ast-editor-mcp"
]
}
}
}Agent | Configuration File Path |
Claude Desktop |
|
Cursor |
|
Windsurf | Agent Panel → "..." → MCP Servers → View raw config |
Antigravity |
|
Gemini CLI |
|
Antigravity IDE
The Antigravity IDE uses its own MCP config file and a uvx-based command — not the uv --directory … run form shown above. Add the server to ~/.gemini/config/mcp_config.json:
Important: Use the absolute path to
uvxfor"command", not a bare"uvx"— Antigravity doesn't inherit your shellPATH. Find it withwhich uvx(e.g./opt/homebrew/bin/uvx).
Note:
uvxignores both this server'suv.lockand the[tool.uv]settings in itspyproject.toml. It re-resolves dependencies on each launch instead of using the locked versions, and the 7-day cooldown is passed explicitly as--exclude-newer "7 days"inargs, so you get the newest compatible releases that are at least 7 days old. This requires uv 0.9.17 or newer: older versions reject the value (invalid value '7 days' for '--exclude-newer <EXCLUDE_NEWER>') and the server fails to start.
{
"mcpServers": {
"ast-editor": {
"command": "/absolute/path/to/uvx",
"args": [
"--exclude-newer",
"7 days",
"--from",
"/absolute/path/to/ast-editor",
"ast-editor-mcp"
]
}
}
}Using Standard Python (Fallback)
If you prefer not to use uv, run the following from the ast-editor folder (the one that contains its pyproject.toml), then point to the .venv executable it creates. python3 must be Python 3.10 or newer.
python3 -m venv .venv && source .venv/bin/activate && pip install .This path doesn't use uv, so the [tool.uv] 7-day dependency cooldown doesn't apply. With pip 26.1 or newer, add --uploaded-prior-to P7D to the pip install command to apply the same cooldown.
{
"mcpServers": {
"ast-editor": {
"command": "/absolute/path/to/ast-editor/.venv/bin/python",
"args": ["-m", "ast_editor.server"]
}
}
}Agent Configuration (Important)
Coding agents are heavily biased toward their default tools. You must explicitly instruct them to use ast-editor when editing code and config files. The agent prompt lives in AST-EDITOR.md — a standalone file you wire into your agent's system instructions. It is kept short, since it is loaded in every session: it covers how to pick and call each tool, and this README is the full reference. The server also sends a short, condensed version of this guidance (start with list_symbols, pick the narrowest tool, what to do when an edit is refused for a syntax error) as MCP server instructions, which some clients, Claude Code among them, pass to the model automatically alongside any prompt file. Wiring in the full prompt file is still recommended. After updating the server, copy the new AST-EDITOR.md over the one you installed (for example ~/.claude/AST-EDITOR.md), since an installed copy does not update itself.
Claude Code / Claude Desktop (via @-include)
Claude Code supports @filename includes in CLAUDE.md. Copy the prompt file into your global config directory and add one include line:
cp /absolute/path/to/ast-editor/AST-EDITOR.md ~/.claude/
echo '@AST-EDITOR.md' >> ~/.claude/CLAUDE.mdOr for a single project, place it next to the project's CLAUDE.md and add @AST-EDITOR.md there.
Other agents (Cursor, Codex CLI, Windsurf, Antigravity, Aider, Gemini CLI, etc.)
Copy the contents of AST-EDITOR.md into your agent's instruction file (AGENTS.md, .cursor/rules/*.mdc, .windsurfrules, .github/copilot-instructions.md, system prompt, etc.). Most non-Claude agents don't support @-include — paste the prompt body directly.
Agent | Instruction file |
Any agent that reads |
|
Cursor |
|
GitHub Copilot |
|
Windsurf |
|
Antigravity |
|
Aider / Gemini CLI / generic | Rules file or system prompt |
Logging & Debugging
The server logs all tool invocations and errors to stderr (safe for stdio transport — does not interfere with JSON-RPC). Logs include timestamps and severity levels.
To inspect logs when running under Claude Desktop, check:
macOS:
~/Library/Logs/Claude/mcp*.logWindows:
%APPDATA%\Claude\logs\mcp*.log
For interactive testing, use the MCP Inspector, which provides a UI for exercising each tool with custom parameters and inspecting responses.
Available Tools
28 toolsadd_fieldA
Add a field or member at the top of a class body: before the first
member, after a Python class docstring or a Java enum's constants
(adding the ; they need), and below the access label a C++ class
opens with. It is indented like the class's members, with a blank line
after it when a method follows. A function target is refused.
Use this when: adding a class attribute, field or member variable. Don't use this when: adding a method (add_method).
Example: class_target="LRUCache" content='version = "1.0"'
| Name | Required | Description | Default |
|---|---|---|---|
| content | Yes | Field or member declaration as source text (e.g. 'version = "1.0"' or Go 'version int'). | |
| file_path | Yes | Absolute path to the source or config file. | |
| class_target | Yes | Class name as list_symbols lists it (a struct, interface or Go struct type too), dotted for nesting ('A.B'). |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations cover the safety profile (mutation, non-destructive, closed world), and the description adds genuinely new behavior: exact insertion point per language, indentation matching, blank-line insertion when a method follows, Java enum semicolon handling, and that a function target is refused. It does not mention error modes beyond the function-target refusal or whether the edit is atomic, 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.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loads the placement behavior, then a crisp use/don't-use pair, then a compact example. Every sentence carries distinct information; nothing is redundant with the schema or annotations.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Output schema exists, so return values need not be described. Placement, formatting side effects, target-type constraints and the sibling alternative are all covered, which is everything an agent needs to call this correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
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 adds value the schema lacks: the sample invocation shows class_target='LRUCache' with dotted-nesting implied, and the refusal rule clarifies what class_target will accept. It does not clarify file_path or content syntax beyond the example.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Add a field or member') and scopes it precisely to a class body, immediately separating it from the sibling add_method. The placement rules across Python, Java and C++ make the operation unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit 'Use this when: adding a class attribute, field or member variable' and 'Don't use this when: adding a method (add_method)', naming the sibling alternative directly. Nothing 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.
add_importA
Add an import line, skipping an exact duplicate. It goes into the group
of imports it belongs with (same package, standard library or not,
relative or not), at its sorted place when the group is sorted, else
after the group's last import. A comment heading the group stays first
(a next-line directive stays on its import), and so do Python from __future__ imports. With no fitting group it goes after the last
import, and a first import after the preamble.
Use this when: importing something the file does not import yet. Don't use this when: adding a name to an existing import (add_import_name).
Example: import_text="from typing import Optional"
| Name | Required | Description | Default |
|---|---|---|---|
| file_path | Yes | Absolute path to the source or config file. | |
| import_text | Yes | Complete import line in the file's language (e.g. 'import os', '#include <stdlib.h>'); in Go a bare spec ('"fmt"') works too. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only declare the safety profile (writes, non-destructive, not open-world); the description adds substantial context beyond that: deduplication of exact duplicates, group placement rules (same package / stdlib / relative), sorted-position vs. after-group fallback, comment headings and next-line directives preserved, `from __future__` pinned first, and the empty-file/preamble case. That is exactly the kind of placement and preservation detail the annotations cannot convey.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with purpose, then placement semantics, then when/when-not, then an example. Every sentence about placement or preservation earns its place; the block is long but not padded. Minor deduction because the routing guidance is buried at the end rather than up front.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists and parameters are fully covered by the schema, so the description need only explain selection and placement behavior — which it does comprehensively, including the fallback cases. 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.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% and both parameters are fully documented (file_path, import_text with language-specific examples). The description's example ('from typing import Optional') largely restates what the schema already shows, so no meaningful meaning is added beyond structured fields. Baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Add an import line') plus a key behavioral qualifier ('skipping an exact duplicate'), and explicitly names the sibling it is not (add_import_name). An agent can distinguish it from add_import_name and remove_import 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.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit 'Use this when: importing something the file does not import yet' and 'Don't use this when: adding a name to an existing import (add_import_name)' with the alternative named. Both the selection condition and the exclusion are stated outright.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
add_import_nameA
Add a name to an existing from <module> import ... (Python) or
import { ... } from "<module>" (JS/TS) statement; a name already
there is left as is. It goes at its sorted place when the names are
sorted (plainly or as isort and ruff sort them), else at the end, in the
list's layout: names one per line give it a line of its own, an inline
list stays inline. Refused when the file has no such import.
Use this when: the module is already imported with named imports. Don't use this when: there is no such import yet, or for a default or namespace import (add_import with the full line).
Example (from typing import Any, cast becomes Any, Dict, cast):
module="typing"
name="Dict"
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | One imported name, e.g. 'Optional'. | |
| module | Yes | Module of the import as written, without quotes (e.g. 'typing' or './utils'). | |
| file_path | Yes | Absolute path to the source or config file. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only declare the generic mutating-but-non-destructive profile; the description adds real behavior: idempotency ('a name already there is left as is'), the exact insertion position (sorted place per isort/ruff, else end), layout preservation (one-per-line vs inline), and the failure mode ('Refused when the file has no such import'). That is precisely the context the annotations cannot carry.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the core action, then structured into when/when-not and a worked example, so an agent can stop reading once it has what it needs. The placement/layout paragraph is long but each clause changes behavior; the only marginal cost is the explicit example block.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 3-required-param mutation tool, the description covers preconditions, insertion semantics, failure behavior, and forwarding to the sibling tool; an output schema exists so return values need no explanation. Nothing an agent needs to call this correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3; the description goes further by grounding all three parameters in a concrete before/after example (`from typing import Any, cast` -> `Any, Dict, cast`) with module and name values, which demonstrates the 'as written, no quotes' convention in practice. It does not, however, say anything about file_path beyond what the schema already states.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Specific verb+resource: adds a single name to an existing named-import statement, with the exact syntax for both Python and JS/TS spelled out. It is clearly distinguished from the siblings add_import (full line / default / namespace imports) and remove_import_name (the inverse operation).
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Has explicit 'Use this when' and 'Don't use this when' sections, and names the alternative tool (add_import with the full line) plus the precondition that the module is already imported with named imports. The refusal case (no such import) is stated as a routing signal, not left to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
add_keyA
Add a key-value pair to a JSON object, YAML mapping, TOML table, Python dict literal or JS/TS object literal. The entry follows the container's layout: one key per line stays so, an inline object stays inline, and a trailing comma is kept. A YAML key with no value gets a nested mapping. A key the container already has is refused, naming the target to give replace_value.
Use this when: the key does not exist yet. Don't use this when: the key exists (replace_value), or you add a list item (append_to_array).
Example (TS, const CONFIG = { server: {...} }): parent_target="CONFIG.server" key="port" value="8080"
| Name | Required | Description | Default |
|---|---|---|---|
| key | Yes | Key to add. JSON, YAML and JS/TS: one name, quoted for you when needed. TOML: a dotted key, so quote a name with a dot yourself ('"example.com"'). Python: a key expression, so quote string keys ('"timeout"'). | |
| value | Yes | Value as source text in the file's syntax, strings quoted (e.g. '"2.0.0"' or '42'). | |
| file_path | Yes | Absolute path to the source or config file. | |
| parent_target | Yes | Parent container: its key path from the top level in a config file ('' for the root; quote a key with dots, 'a."b.c"'), or a Python or JS/TS module-level variable's name, dotted into nested literals ('CONFIG.server'). |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes well beyond the annotations (readOnlyHint=false, destructiveHint=false, openWorldHint=false) by disclosing preservation behavior (one key per line stays so, inline objects stay inline, trailing comma kept), a format-specific rule (YAML key with no value becomes a nested mapping), and error behavior (existing key is refused and the error names replace_value). These are exactly the traits an agent cannot infer from structured fields.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the action, then behavior, then a Use/Don't-use block, then a compact example. Every sentence carries information; no filler or restatement of the tool name.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Output schema exists, so return values need not be described, and annotations cover the safety profile. The description fills the remaining gaps: container layout preservation, format-specific YAML behavior, duplicate-key failure, and concrete parameter composition.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the schema already carries the per-parameter meaning (dotted keys for TOML, key expressions for Python, source-text values), making 3 the baseline. The worked example showing parent_target="CONFIG.server" together with key/value adds real compositional meaning beyond the schema, earning a bump.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (add) and resource (a key-value pair) and enumerates the concrete container formats it applies to: JSON object, YAML mapping, TOML table, Python dict, JS/TS object literal. It also names the sibling tools it is not (replace_value, append_to_array), so an agent can route without opening any schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit 'Use this when: the key does not exist yet' and 'Don't use this when: the key exists (replace_value), or you add a list item (append_to_array)' gives both the positive condition and two named alternatives. Nothing 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.
add_methodA
Add a method at the end of a class body, after its last member, spaced like the class's methods. In Go it goes after the type declaration. In a C++ class whose last method is followed by an access label, it goes right after that method, so it gets the same access. A one-line Python or Ruby class is refused, and so is a function target (use insert_in_body).
Use this when: adding a method to an existing class. Don't use this when: adding a field (add_field) or a top-level function (add_top_level).
Example: class_target="LRUCache" content='def clear(self):\n self.items.clear()'
| Name | Required | Description | Default |
|---|---|---|---|
| content | Yes | Complete method source, re-indented like the class's members, keeping its own relative indentation. | |
| file_path | Yes | Absolute path to the source or config file. | |
| class_target | Yes | Class name as list_symbols lists it (a struct, interface or Go struct type too), dotted for nesting ('A.B'). |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only declare safety hints (readOnly false, destructive false, closed world); the description adds substantial behavior: placement rules across Go/C++/Python/Ruby, refusal conditions for one-line classes and function targets, and indentation/spacing behavior. Nothing contradicts the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the core behavior, then use/don't-use bullets and a compact example. Every sentence earns its place—language-specific rules are necessary precision, not padding.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given an output schema, annotations, and full schema coverage, the description covers everything an agent needs to call this correctly: placement per language, refusals, target restrictions, and an example. No material gaps remain.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so all three parameters are already well documented; the baseline is 3. The description doesn't add syntactic meaning to file_path or class_target beyond the schema, though the example clarifies content shape (full method source including def line).
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource (add a method to a class body) and precisely defines where it is placed. The language-specific clauses (Go after type declaration, C++ after access label, refusal of one-line Python/Ruby classes) make it unmistakable against siblings like add_field or add_top_level.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly provides 'Use this when' and 'Don't use this when' sections, naming the alternatives add_field and add_top_level. It also redirects function targets to insert_in_body, so the agent knows exactly which sibling to pick.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
add_parameterA
Add one parameter to a function's signature, keeping the body. "end"
puts it after the last parameter but before those that must come after
it (Python **kwargs, a JS/TS rest parameter, Go and Java variadics,
C/C++ ..., Ruby **opts and &blk); "start" before the first, but
after a TS this or Java receiver parameter. A list written one
parameter per line gets it on a line of its own, a C (void) takes it
in place of void, and a bare JS/TS arrow parameter gets parentheses.
A name the function already has is refused.
Use this when: adding a parameter without retyping the signature. Don't use this when: rewriting the signature (replace_signature), or changing the body too (replace_function).
Example (def f(a, **kw) becomes def f(a, b, **kw)):
target="f"
parameter="b"
| Name | Required | Description | Default |
|---|---|---|---|
| target | Yes | Function or method name as list_symbols lists it, dotted for nesting ('LRUCache.get'); overloads take parameter types ('A.m(int)'). | |
| position | No | 'end' (default) after the last parameter, before any that must stay last; 'start' before the first. Other values are refused. | end |
| file_path | Yes | Absolute path to the source or config file. | |
| parameter | Yes | Source text of one parameter (e.g. 'default=None', 'const int* buf'); the comma is added for you. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations cover the safety profile (readOnlyHint=false, destructiveHint=false) but say nothing about semantics. The description adds real behavioral detail the annotations cannot: language-specific placement rules for 'end'/'start', formatting side effects (one-param-per-line, C `(void)` replacement, arrow-function parenthesization), and the duplicate-name refusal. It stops short of stating that the file is rewritten in place or what the response contains, which keeps it at 4 rather than 5.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the purpose, then when/when-not, then a worked example — a good ordering with no filler sentences. The long parenthetical enumerating every language's trailing constructs is justified but dense, slightly weighing down the opening sentence.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With full schema coverage, an output schema, and safety annotations already supplied, the description fills the remaining gaps: exact placement behavior, refusal cases, and formatting side effects. An agent has everything needed to call it correctly on the first try.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
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 goes further by explaining concretely what 'end' and 'start' mean per language ('before those that must come after it… Python **kwargs, a JS/TS rest parameter…') and by showing an example mapping target/parameter to a before/after signature. This adds meaning beyond the schema's abstract wording.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Opens with a precise verb + resource scope: 'Add one parameter to a function's signature, keeping the body.' That single clause distinguishes it from remove_parameter, replace_signature and replace_function_body without needing to open any schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit 'Use this when: adding a parameter without retyping the signature' and 'Don't use this when: rewriting the signature (replace_signature), or changing the body too (replace_function)' — naming both alternatives and the condition that selects them.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
add_top_levelA
Add top-level code (a function, class, constant or other statement) to a source file. "bottom" appends it at the end, inside a header's include guard; "top" puts it after the preamble, before the first declaration. It is set apart by a blank line, two around a Python def or class, but one-line code added at the bottom under stacked one-line code is stacked too. In Go, or a file indented with tabs, its indentation becomes tabs.
Use this when: adding a top-level symbol or statement. Don't use this when: placing it next to a symbol (insert_sibling), in a class (add_method, add_field), in a body (insert_in_body) or in a config file (add_key).
Example: content="MAX_CONNECTIONS = 10" position="top"
| Name | Required | Description | Default |
|---|---|---|---|
| content | Yes | Top-level code, inserted as written; read_symbol's text of a nested symbol is moved to column 0 as a whole. | |
| position | No | 'bottom' (default) at the end of the file; 'top' after the preamble (package clause, `#!` and magic comments, module docstring, directives such as 'use strict', imports and includes). Other values are refused. | bottom |
| file_path | Yes | Absolute path to the source or config file. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=false and destructiveHint=false, so safety is covered; the description adds real behavioral detail beyond that — placement inside a header's include guard for 'bottom', blank-line separation rules, and tab conversion in Go or tab-indented files. It stops short of stating what happens on conflicts (e.g., duplicate symbol names) or failure modes, which keeps it at 4 rather than 5.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the verb and resource, then positions, then use/don't-use, then an example — a sensible ordering. The blank-line and tab-indentation rules are somewhat dense, but each sentence describes observable behavior an agent would otherwise get wrong, so little is wasted.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema, full annotations, and 100% parameter coverage, the description need only cover placement semantics and sibling routing — and it does both, including language-specific formatting behavior. Nothing required to invoke the tool correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
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 adds placement nuance not fully in the schema — that 'bottom' lands inside an include guard and 'top' goes after the preamble but before the first declaration — plus a concrete example of content/position usage. The content parameter's column-0 behavior is left to the schema, which already documents it.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Add top-level code ... to a source file') and enumerates what counts as top-level (function, class, constant, other statement). It also disambiguates from sibling tools by naming them, so an agent can distinguish it from insert_sibling or add_method 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.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit 'Use this when' and 'Don't use this when' sections, with each exclusion routed to a named alternative (insert_sibling, add_method, add_field, insert_in_body, add_key). The condition that selects this tool versus each alternative is spelled out, leaving nothing to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
append_to_arrayA
Append a value to a JSON, YAML or TOML array or a Python module-level
list. The value follows the array's layout: an inline array stays
inline ([1, 2] becomes [1, 2, 3]), one element per line gets a new
line, and a trailing comma is kept. Comments are not elements: the
comma goes before them.
Use this when: adding a list item. Don't use this when: adding a key-value pair (add_key).
Example: target="project.dependencies" value='"new-package"'
| Name | Required | Description | Default |
|---|---|---|---|
| value | Yes | Value as source text in the file's syntax, strings quoted (e.g. '"2.0.0"' or '42'). | |
| target | Yes | Key path from the top level to a JSON, YAML or TOML array ('project.dependencies'), or a Python module-level list's name. | |
| file_path | Yes | Absolute path to the source or config file. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only declare the safety profile (readOnly=false, destructive=false, openWorld=false); the description adds genuinely non-obvious behavior — layout-preserving formatting, comma placement before comments, trailing-comma retention. It stops short of stating what happens when the target is missing or not an array, which matters for an in-place mutation.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with purpose, then formatting rules, then usage gates, then a compact example — no filler. The formatting paragraph is slightly dense but every clause conveys distinct behavior.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With annotations covering safety, an output schema covering return values, and full parameter documentation in the schema, the description supplies the remaining caller-critical knowledge: supported formats, formatting preservation, and the sibling to use instead. Nothing needed to invoke it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the schema baseline already applies. The description still adds value by showing the concrete call shape (target="project.dependencies", value='"new-package"'), reinforcing that value is raw source text in the file's syntax rather than a serialized type.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource ('Append a value to a JSON, YAML or TOML array or a Python module-level list') and enumerates the supported formats. It explicitly sets itself apart from the closest sibling, add_key, so an agent can route correctly without opening either schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It uses an explicit 'Use this when / Don't use this when' structure and names the alternative tool (add_key) for the key-value case. The positive condition ('adding a list item') borders on restating the name, and no guidance is given relative to remove_from_array or insert_sibling, so it falls short of a full 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
delete_in_bodyADestructive
Delete a snippet inside a function's body, matched as replace_in_body
matches one. A deletion that empties its lines removes them whole; a
comment after the snippet on its last line stays. One that would leave
a Python body without a statement is refused (replace the snippet with
pass).
Use this when: removing a statement, block or line in a body, or an entry of an object literal passed as an argument. Don't use this when: deleting a whole function or class (delete_symbol).
Example: target="RegisterRoutes" snippet='r.Mount("/kb", kbHandler)'
| Name | Required | Description | Default |
|---|---|---|---|
| target | Yes | Function or method name as list_symbols lists it, dotted for nesting ('LRUCache.get'); overloads take parameter types ('A.m(int)'). | |
| snippet | Yes | Text in the target's body, matching one place: its exact text at token boundaries, or else whole lines with the same indentation added to or removed from each. | |
| file_path | Yes | Absolute path to the source or config file. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
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 earns credit by disclosing the non-obvious semantics beyond that: lines that empty are removed whole, a trailing comment on the last line survives, and a deletion that would empty a Python body is refused with a prescribed workaround. It stops short of describing what is returned or how other failure modes surface, so a 4 rather than 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.
Is the description appropriately sized, front-loaded, and free of redundancy?
Dense but every sentence carries content: behavior, exclusions, and an example. Front-loading the behavioral rules ahead of the use/don't-use rubric is slightly inverted for scanning, but nothing is redundant.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Three required parameters, all schema-documented at 100%, an output schema exists so return values need no prose, and annotations cover the destructive profile. The description supplies exactly the remaining gaps: matching semantics, edge-case behavior, and sibling routing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so baseline is 3; the description goes beyond it with a concrete example pairing target="RegisterRoutes" with snippet='r.Mount("/kb", kbHandler)', showing the target/snippet relationship in practice. It adds no syntax detail for file_path and defers snippet matching rules to replace_in_body, so not a 5.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (Delete) plus a precise resource scope (a snippet inside a function's body), and immediately distinguishes itself from the broad-brush alternative by naming delete_symbol. An agent can tell it apart from replace_in_body and 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.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit 'Use this when' enumerates the concrete cases (statement, block, line, object-literal entry as argument) and an explicit 'Don't use this when' routes whole-function/class removal to delete_symbol. That is a complete when/when-not with a named alternative.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
delete_keyADestructive
Delete a key-value pair from a config file, or from a Python or JS/TS
module-level dict or object literal. The adjacent comma goes too where
the syntax has one, and deleting the only entry leaves {}; YAML and
TOML keys otherwise go with their lines.
Use this when: removing a whole entry. Don't use this when: removing a list item (remove_from_array), or an entry of an object literal passed as an argument (delete_in_body).
Example: target='CONFIG."timeout"'
| Name | Required | Description | Default |
|---|---|---|---|
| target | Yes | Key path from the top level in a config file ('dependencies.tree-sitter'; quote a key with dots, '"editor.fontSize"'), or a path into a Python or JS/TS module-level dict or object ('CONFIG."timeout"', 'CONFIG.server.port'). | |
| file_path | Yes | Absolute path to the source or config file. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true and openWorldHint=false, so safety is covered; the description goes further and discloses the concrete side effects of deletion — adjacent comma removal, `{}` left behind for the last entry, line removal for YAML/TOML. It stops short of saying what happens if the target key does not exist (error vs. no-op), which is the one behavioral detail still missing.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the core action, then syntax consequences, then the use/don't-use routing block, then a single example. Every sentence carries distinct information and the sectioning makes it scannable.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists and annotations cover the safety profile, so return values and risk need not be explained. Parameters are fully documented. The only remaining gap is failure semantics for a missing key, which matters for a destructive edit but is not stated.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% and the `target` parameter already documents the dotted-path and quoted-key syntax. The description's example (`target='CONFIG."timeout"'`) illustrates the same format but adds no new constraint or edge case 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.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource (delete a key-value pair) and immediately bounds the scope to config files and Python/JS/TS module-level dicts/object literals. It explicitly names the siblings it is not (remove_from_array, delete_in_body), so an agent can route correctly 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.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Uses explicit 'Use this when' / 'Don't use this when' sections with two named alternatives and the exact condition that selects each. This is the strongest form of routing guidance and leaves nothing to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
delete_symbolADestructive
Delete a whole function, method, class or other symbol, with its
decorators, a JS/TS export and a C++ template <...> header. The
blank lines that set it apart go too, so the file keeps its spacing. A
symbol that shares a line with other code is cut out of the line. One
name of a declaration of several (int a, b;, struct S {...} s;) is
refused: give replace_function the declaration without it. Refused in
JSON, YAML and TOML files (use delete_key).
Use this when: removing a symbol along with its doc comment. Don't use this when: removing a config key (delete_key), an import (remove_import) or lines inside a body (delete_in_body).
Example: target="LRUCache.old_method"
| Name | Required | Description | Default |
|---|---|---|---|
| target | Yes | Symbol name as list_symbols lists it, dotted for nesting (e.g. 'LRUCache.old_method', 'A.m(int)'). | |
| file_path | Yes | Absolute path to the source or config file. | |
| include_leading_comments | No | True (default) also deletes the comment block above the symbol, or before it on its first line; false keeps it. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true, but the description goes well beyond that: it discloses exactly what is removed (decorators, export keyword, template header, blank lines, optionally the doc comment), what is refused (multi-name declarations, JSON/YAML/TOML files), and how shared-line symbols are handled. This is the level of destruction detail an agent needs before calling a destructive edit.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the core action and its scope, then structured into when/when-not and an example. Every sentence carries information, though the opening paragraph is dense enough that a slightly tighter split would read faster.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a destructive, file-type-restricted edit tool, the description covers scope, refusals, alternatives and target addressing. An output schema exists, so return values need no explanation, and nothing an agent needs in order to call this correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so both required parameters are already documented, including the dotted 'LRUCache.old_method' form and the include_leading_comments default. The description still adds real semantics by specifying that a single name from a multi-name declaration is refused and must be handled via replace_function — a constraint on the target parameter not present in the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Delete a whole function, method, class or other symbol') and enumerates precisely what the deletion encompasses: decorators, a JS/TS export, a C++ template header, and surrounding blank lines. An agent can distinguish this from replace_function or delete_key without opening any schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Includes explicit 'Use this when' and 'Don't use this when' sections that name three concrete alternatives (delete_key, remove_import, delete_in_body) and the condition selecting each. It also routes the multi-name-declaration case to a specific sibling, so there is no ambiguity left to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
edit_leading_commentADestructive
Add, replace or remove the comment block directly above a symbol, its
doc comment. The block sits above the symbol's decorators, annotations,
export and C++ template <...> header, and a new comment goes there,
re-indented to the symbol. A comment indented deeper than the symbol
ends the code above and is not part of the block. A symbol that other
code comes before on its line is refused. In YAML and TOML the target
is a key path or a TOML [table]; JSON has no comments and is refused.
Use this when: adding, rewriting or deleting a symbol's doc comment. Don't use this when: writing a Python docstring (replace_docstring) or a comment inside a body (insert_in_body, replace_in_body).
Example: target="LRUCache.get", op="add", comment="# Return the cached value."
| Name | Required | Description | Default |
|---|---|---|---|
| op | Yes | 'add' inserts a comment, refused when the symbol has one (the error quotes it: use 'replace' with a block that repeats lines to keep, such as lint directives); 'replace' replaces the block, or adds one; 'remove' deletes it. Other values are refused. | |
| target | Yes | Symbol name as list_symbols lists it, dotted for nesting ('LRUCache.get'), or a YAML/TOML key path from the top level or TOML [table] name ('tool.uv'). | |
| comment | No | Comment text with its markers ('# note', '// note', '/** ... */'); required for 'add' and 'replace', ignored for 'remove'. | |
| file_path | Yes | Absolute path to the source or config file. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only say destructiveHint=true/readOnly=false, but the description adds the real behavioral context: indentation is rewritten to match the symbol, a comment indented deeper than the symbol terminates the code above, symbols with preceding code on their line are refused, JSON has no comments and is refused, and YAML/TOML targets are key paths or [table] names. This is exactly the mutation-risk detail the annotations cannot express.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The scoping facts (where the block goes, indentation, refusals) come first, then the use/don't-use routing, then a compact example. Every clause carries a distinct rule; there is no filler despite the length.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Output schema exists so return values need no explanation, and the description still covers all four parameters' behavior indirectly plus the language-specific edge cases (YAML/TOML/JSON) and the refusal conditions. For a destructive, file-mutating tool, 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.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the baseline of 3 is met by the schema alone; the description adds value by giving a worked example (`target="LRUCache.get"`, `op="add"`) that shows the dotted-symbol targeting convention in use. It does not restate `op` refusal rules or `comment` requirements, which live in the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific triple of operations ('Add, replace or remove') on a precisely scoped resource ('the comment block directly above a symbol, its doc comment'), with the boundary of what counts as the block spelled out (sits above decorators, annotations, `export`, C++ `template <...>` headers). An agent can immediately distinguish it from `insert_in_body`, `replace_in_body` or `replace_docstring`.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit 'Use this when' and 'Don't use this when' clauses, and the exclusions name the exact sibling tools (`replace_docstring`, `insert_in_body`, `replace_in_body`) plus the condition (Python docstring, comment inside a body) that routes the agent away. Nothing left to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
find_referencesARead-only
List each occurrence of an identifier in a source file as line N: <source line>, in file order. Read-only and syntactic, with no scope
analysis, so unrelated identifiers of the same name show up too. C++
destructors and operators go by their list_symbols names (~A,
operator==).
Use this when: surveying a name's uses in a file before a rename. Don't use this when: you need references across files or by scope (use a language server).
Example: target="LRUCache"
| Name | Required | Description | Default |
|---|---|---|---|
| target | Yes | Identifier to find, a plain name, not a dotted path (e.g. 'LRUCache'). | |
| file_path | Yes | Absolute path to the source or config file. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare a safe read-only profile, and the description adds substantive context beyond them: the analysis is syntactic with no scope analysis, so false-positive matches occur, plus how C++ destructors and operators are named. This materially changes how an agent should interpret results.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with purpose, then structured when/when-not blocks and a short example — efficient overall. The trailing example largely duplicates the schema's own example, so it is mildly redundant but not wasteful.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With annotations, a 100%-covered two-param schema, and an output schema, the description supplies exactly the missing pieces: output format, the syntactic-analysis caveat, and routing to a language server when scope matters.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so both parameters are already documented, including the 'plain name, not a dotted path' constraint and the LRUCache example. The description's example repeats that guidance rather than adding new meaning.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource (list each occurrence of an identifier in a source file) and even fixes the output shape (`line N: <source line>`, file order). It is clearly distinguishable from siblings like list_symbols or read_symbol.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit 'Use this when: surveying a name's uses in a file before a rename' and 'Don't use this when: you need references across files or by scope (use a language server)' — both the trigger and the alternative are named.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
insert_in_bodyA
Insert new_snippet inside a function's body. Set exactly one of at,
after or before. at="top" goes after a Python docstring,
at="bottom" at body level after the last statement, and in an empty
body one level deeper than the function; at is refused for a body on
its signature's line (use replace_function_body).
An anchor is matched as replace_in_body matches a snippet and must be
unique. One that ends its line (after) or starts it (before) gets
new_snippet on lines of its own; after a line that opens a block (if x:, if (x) {), new lines go inside the block. A mid-line anchor gets
new_snippet byte for byte.
Use this when: adding lines to a body. Don't use this when: replacing the whole body (replace_function_body), changing existing lines (replace_in_body), or adding a top-level symbol (add_top_level).
Example (both written without indentation): target="handle" new_snippet='auth_check(request)' before='validate(request)'
| Name | Required | Description | Default |
|---|---|---|---|
| at | No | 'top' or 'bottom' of the body; '' (default) leaves this mode unused. Other values are refused. | |
| after | No | Anchor in the body to insert after; '' (default) leaves this mode unused. | |
| before | No | Anchor in the body to insert before; '' (default) leaves this mode unused. | |
| target | Yes | Function or method name as list_symbols lists it, dotted for nesting ('LRUCache.get'); overloads take parameter types ('A.m(int)'). | |
| file_path | Yes | Absolute path to the source or config file. | |
| new_snippet | Yes | Text to insert. With at, re-indented as a block to the body's indentation; with after or before, indented like the anchor (as written when already at the file's indentation there). |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes well beyond the annotations: it discloses refusal cases ("`at` is refused for a body on its signature's line"), the uniqueness constraint on anchors, and the empty-body / docstring positioning rules. It does not cover failure behavior for a missing target or unparsable file, so it falls just short of exhaustive.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the action and the one-of-three rule, then when/when-not, then a compact example. Dense but every clause carries information; only the parenthetical language-specific hints slightly interrupt the flow.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values need not be explained, and all six parameters are documented. For a mutation tool with real edge cases (empty body, signature-line body, block-opening anchors), the description supplies the positioning, indentation, and refusal semantics an agent needs to call it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
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 adds meaning the schema does not carry: what `at="top"` means relative to a Python docstring, where `at="bottom"` lands in an empty body, and how indentation is applied for anchored versus `at` insertion. Anchor matching semantics (uniqueness, line-opening versus mid-line) are additional and useful.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ("Insert new_snippet inside a function's body") and immediately pins the scope with the mutual-exclusion rule for `at`/`after`/`before`. It is clearly distinguishable from replace_in_body and replace_function_body, which it names.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit "Use this when: adding lines to a body" and "Don't use this when:" enumerating three alternatives with the condition that selects each (replace_function_body, replace_in_body, add_top_level). Nothing about tool selection 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.
insert_siblingA
Insert code next to a named symbol, at its level. "before" goes above
the symbol's leading comment, decorators and export; "after" below
the symbol (after the ; that ends a C/C++ class). The code is spaced
like the gap it goes into: one-line code stacked without blank lines
stays stacked, and next to a function or class it gets at least one
blank line, two around a top-level Python def or class. A comment
indented deeper than the target ends the code above, so "before" goes
below it. "before" is refused when other code comes before the target
on its line, "after" when code follows it. Refused in JSON, YAML and
TOML files (use add_key).
Use this when: placing code relative to a symbol, such as a helper above its caller. Don't use this when: appending at the end of the file (add_top_level), or inserting into a body (insert_in_body) or a class (add_method, add_field).
Example: target="LRUCache" content="CACHE_SIZE = 100" position="before"
| Name | Required | Description | Default |
|---|---|---|---|
| target | Yes | Symbol name as list_symbols lists it, dotted for nesting (e.g. 'LRUCache', 'A.m'). | |
| content | Yes | Code to insert, re-indented to the target's level (in tabs where the file indents with them); read_symbol's text goes in as a whole. | |
| position | Yes | 'before' or 'after' the target; other values are refused. | |
| file_path | Yes | Absolute path to the source or config file. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the annotations (which only say this is a non-read-only, non-destructive local write), the description discloses exact placement semantics (above leading comments/decorators/export vs. below the terminating ';'), how blank-line spacing is derived from the surrounding gap, the deeper-indented-comment edge case, and two refusal conditions (code already on the line before/after the target). It also states format-level refusals (JSON/YAML/TOML) not captured by 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.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the core action, then rules, then when/when-not, then example — a sound structure. The spacing paragraph is dense and could be tightened, but every sentence carries operative information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With annotations covering safety, an output schema covering returns, and full schema coverage on all four parameters, the description only needs to supply placement semantics and refusals — which it does thoroughly. An agent has everything needed to call this correctly on the first attempt.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so baseline is 3; the description adds real value by clarifying what 'before'/'after' mean positionally, which the schema only reduces to a string enum-like value. The example then demonstrates target/content/position concretely. It does not restate the dotted-nesting or re-indentation behavior already covered in the schema descriptions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The first sentence states a specific verb (Insert), resource (code), and placement rule (next to a named symbol, at its level). It is immediately distinguishable from add_top_level, insert_in_body, add_method, and add_field, all of which are named as alternatives later.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit 'Use this when' and 'Don't use this when' blocks name the correct condition and route each wrong-condition case to a specific sibling (add_top_level, insert_in_body, add_method, add_field, add_key). There is also a worked example, so nothing 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.
list_symbolsARead-only
List the symbols of a source file, one per line as <kind> <name> (line N), class members indented under their class (method A.B.m). Each
name is the target the other tools take: overloads with their
parameter types (A.m(int)), a C++ definition outside its class by
its qualified name (A::f), and a struct or TS type that shares its
name with another symbol after its keyword (struct struct stat
targets struct stat). Kinds include function, method, class, struct,
enum, interface, namespace, type, macro, field, variable and constant;
a Go var x = func(...) {...}, listed as a variable, also takes the
body, parameter and signature tools. A name with a prototype or
forward declaration is listed once, at its definition. Read-only.
Use this when: before editing a file, to get exact target names. Don't use this when: you already know the target (read_symbol reads one symbol).
Example: file_path="/abs/path/to/module.py"
| Name | Required | Description | Default |
|---|---|---|---|
| file_path | Yes | Absolute path to the source or config file. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, destructiveHint=false and openWorldHint=false, so the trailing 'Read-only.' is largely redundant. The description still earns credit for behavioral detail the annotations cannot carry: prototype/forward declarations are listed once at the definition, and Go `var x = func(...)` entries also work with body/parameter/signature tools — non-obvious rules that affect how an agent reuses the returned names.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the core behavior and output format, then usage rules, then an example — a sensible ordering. The long enumeration of kinds and edge cases (overloads, C++ qualified names, `struct struct stat`) is dense but each item disambiguates a real target-name case; only the redundant 'Read-only.' line fails to earn its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a one-parameter listing tool with an output schema and full annotation coverage, nothing an agent needs is missing: output line format, target-name conventions per language, dedup rules, and the routing decision against read_symbol are all present.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Only one parameter and schema description coverage is 100%, so the schema already fully documents `file_path` as an absolute path. The description's example (`file_path="/abs/path/to/module.py"`) merely restates that format rather than adding new semantics, so this sits at the baseline.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('List the symbols of a source file') and immediately specifies the exact output shape (`<kind> <name> (line N)`, indented members). It also pre-empts confusion with the mutation siblings by explaining that each listed name is the exact target string the other tools consume.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit 'Use this when: before editing a file, to get exact target names' and 'Don't use this when: you already know the target (read_symbol reads one symbol).' The alternative sibling is named with the condition that selects it, so no inference is required.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
read_importsARead-only
Return the import statements of a source file (imports, includes, Ruby requires), without reading the rest. Read-only.
Use this when: checking a file's dependencies, as before add_import. Don't use this when: changing imports (add_import, remove_import).
Example: file_path="/abs/path/to/module.py"
| Name | Required | Description | Default |
|---|---|---|---|
| file_path | Yes | Absolute path to the source or config file. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, so the 'Read-only' line is redundant, but the description adds genuine behavioral context: it returns only the import section 'without reading the rest' of the file, implying a cheaper partial read. That is useful beyond the annotation set, though nothing is said about edge cases like files with no imports.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Well front-loaded with purpose first, then usage routing, then example. The standalone 'Read-only.' sentence is largely waste given the annotations, but overall it is tight.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists so return values needn't be described, the single parameter is fully documented, and the read-only nature is covered by both annotations and text. Nothing an agent needs to invoke it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and the single parameter is already documented as an absolute path, so the schema does the heavy lifting. The example is essentially a restatement of that guidance, adding minimal semantic value beyond the structured field.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Return the import statements of a source file') and clarifies scope by naming the supported forms (imports, includes, Ruby requires). It is immediately distinguishable from siblings like add_import and remove_import.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly gives a 'Use this when' condition (checking dependencies, before add_import) and a 'Don't use this when' exclusion routing to add_import/remove_import. No inference required.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
read_symbolARead-only
Return the source of one symbol (function, class, method, variable) or
the value of a config key, without reading the whole file. Read-only.
"full" is the text replace_function and delete_symbol take: decorators,
a JS/TS export, a C++ template <...> header and code that only
wraps the symbol (a Go type, a closure's key, a C typedef)
included, a C/C++ class ending with its ;. It starts at the symbol's
first byte, the later lines at their file indentation. "interface"
gives a class's header, fields and method signatures (bodies as
...), indented as in the class, or a function's signature;
"signature" the signature or class header alone, after decorators.
Both refuse a variable, constant, field, type alias or macro, saying
what it is. A name with a prototype or forward declaration reads as
its definition.
Use this when: reading one symbol; pick the narrowest depth. Don't use this when: you need the file's outline (list_symbols) or its imports (read_imports).
Example: target="LRUCache", depth="interface"
| Name | Required | Description | Default |
|---|---|---|---|
| depth | No | 'full' (default) the whole symbol; 'interface' a class skeleton or function signature; 'signature' the signature or class header. Config files take only 'full'. Other values are refused. | full |
| target | Yes | Symbol name as list_symbols lists it, dotted for nesting ('LRUCache.get', 'A.m(int)'), or a config key path from the top level ('project.version'; quote a key with dots, '"editor.fontSize"'). | |
| file_path | Yes | Absolute path to the source or config file. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare read-only/non-destructive, so the description's real value is the disclosure of output semantics that no structured field carries: exactly what 'full' text includes (decorators, JS/TS export, C++ template header, Go type wrappers, C typedefs, class trailing ';'), where the text starts and how later lines are indented, and that 'interface'/'signature' refuse variables, constants, fields, type aliases and macros with an explanatory error. Prototype/forward-declaration resolution to the definition is also a behavioral trait worth knowing.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the purpose, then the depth semantics, then a clearly labeled use/don't-use block and an example — good structure. The middle paragraph is unusually dense (a single sentence enumerating Go types, typedefs, template headers, closure keys), which costs some readability but every clause carries real information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema present and full parameter coverage, the description need only cover call semantics — and it does: depth choice, target naming, config-file restriction to 'full', and how symbols with prototypes resolve. Nothing an agent needs to invoke this correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3; the description nonetheless adds meaning the schema does not, notably the concrete shape of each depth's text and the refusal behavior of the narrower depths. The target-format detail (dotted nesting, quoted dotted config keys) duplicates the schema rather than extending it, which keeps it from a 5.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Return the source of one symbol ... or the value of a config key') plus the key benefit ('without reading the whole file'), which immediately separates it from file-level readers. The 'Use this when / Don't use this when' block names list_symbols and read_imports as the alternatives, so the agent can route 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.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit two-sided guidance: 'Use this when: reading one symbol; pick the narrowest depth' and 'Don't use this when: you need the file's outline (list_symbols) or its imports (read_imports)'. The alternatives are named with the exact condition that selects them, and the depth-selection heuristic is stated.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
remove_from_arrayADestructive
Remove the first element matching value_match from a JSON, YAML or
TOML array or a Python module-level list. An element on a line of its
own goes with that line and its comment; other comments stay. The
trailing-comma style is kept, and removing the only element leaves
[].
Use this when: removing one list item. Don't use this when: removing a whole key (delete_key).
Example: target="project.dependencies" value_match='"old-package"'
| Name | Required | Description | Default |
|---|---|---|---|
| target | Yes | Key path from the top level to a JSON, YAML or TOML array ('project.dependencies'), or a Python module-level list's name. | |
| file_path | Yes | Absolute path to the source or config file. | |
| value_match | Yes | Element to remove, compared with each element's source text, whitespace stripped (e.g. '"old-package"'). |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already flag destructiveHint=true and readOnlyHint=false, and the description goes well beyond them: only the first match is removed, the element's own line and comment are removed while other comments stay, trailing-comma style is preserved, and removing the sole element yields `[]`. The one gap is behavior on no-match (no-op, error, or silent success), which matters for a destructive edit.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the core semantics, then a matching-detail paragraph, then structured Use/Don't-use lines and a compact example. Every sentence carries actionable information; nothing is filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values need no explanation, and the formatting/matching rules are unusually complete. The missing piece is failure behavior when value_match matches nothing and whether matching is case- or whitespace-sensitive beyond the stated whitespace-stripped comparison.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3, and the description largely restates the documented parameters via the example (target, value_match). It does add one non-obvious semantic — that only the first matching element is removed rather than all matches — which is why it holds at the baseline rather than dropping.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a precise verb+resource: 'Remove the first element matching value_match from a JSON, YAML or TOML array or a Python module-level list.' It also names the sibling it must not be confused with (delete_key), so an agent can select it without opening any schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Contains explicit 'Use this when: removing one list item' and 'Don't use this when: removing a whole key (delete_key)' clauses, giving both the positive trigger and the exclusion with the named alternative.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
remove_importADestructive
Remove an import line, matched by its text with surrounding whitespace stripped.
Use this when: removing an unused import. Don't use this when: removing one name from a multi-name import (remove_import_name).
Example: import_text="import os"
| Name | Required | Description | Default |
|---|---|---|---|
| file_path | Yes | Absolute path to the source or config file. | |
| import_text | Yes | Exact import line to remove (e.g. 'import os'). |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
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 the file. The description adds the whitespace-stripping match rule, which is genuine behavioral context, but it says nothing about what happens when the import is not found, whether the file must exist, or whether the file is rewritten/backed up. With annotations covering the safety profile, this is adequate but not rich.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Purpose statement first, then when/when-not, then a one-line example — everything is front-loaded and every sentence carries routing or matching information. No filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists so return values need no explanation, parameters are fully covered, and the alternative tool is named. The remaining gap is failure behavior (no matching line found) for a destructive, file-mutating operation, which an agent would benefit from knowing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so both parameters are already documented, but the description adds non-obvious semantics the schema lacks: matching is by text with surrounding whitespace stripped. The example import_text="import os" also clarifies the expected string form, which goes beyond 'Exact import line to remove' in the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (Remove) and resource (an import line) plus the matching rule (text with surrounding whitespace stripped). It also names the sibling it is not (remove_import_name), so an agent can distinguish the two without inspecting either schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit 'Use this when: removing an unused import' and 'Don't use this when: removing one name from a multi-name import (remove_import_name)' gives both the trigger condition and the named alternative. That is exactly the routing information needed among the 28 sibling tools.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
remove_import_nameADestructive
Remove one name from a from <module> import ... (Python) or import { ... } from "<module>" (JS/TS) statement. A name on a line of its own
goes with that line and its comment. Removing the only name removes the
statement, but is refused when a default import would be left with
empty braces (import D, { a } from "m"): use remove_import, then
add_import.
Use this when: dropping one name from a multi-name import. Don't use this when: removing the whole import line (remove_import).
Example: module="typing" name="List"
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | One imported name, e.g. 'Optional'. | |
| module | Yes | Module of the import as written, without quotes (e.g. 'typing' or './utils'). | |
| file_path | Yes | Absolute path to the source or config file. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes well beyond the destructiveHint=true annotation by disclosing concrete edit semantics: a name on its own line takes the line and its comment, removing the only name removes the statement, and the default-import empty-braces case is refused with a prescribed workaround (remove_import then add_import). This is exactly the failure-mode context an agent needs before invoking a destructive edit.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded action sentence, then structured Use/Don't-use/Example blocks with no filler. The denser braces-refusal sentence is behaviorally necessary rather than padding.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Output schema exists so return values need no explanation; parameters are fully covered in the schema; and the description supplies the edge cases and refusal behavior that structured fields cannot express.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% and each parameter already documents its format, so baseline is 3. The description's example (module="typing", name="List") illustrates the pairing but largely restates what the schema already says about module and name.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Names a specific verb and resource ('Remove one name from a from-import / import {...} statement') and covers both Python and JS/TS syntax. It is immediately distinguishable from sibling remove_import (whole statement) and add_import_name.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit 'Use this when: dropping one name from a multi-name import' and 'Don't use this when: removing the whole import line (remove_import)', naming the alternative tool and the condition that selects it.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
remove_parameterADestructive
Remove a parameter by name from a function's signature, keeping the
body. A parameter on a line of its own goes with that line and its
comment. Removing the only one leaves (), or (void) in C. In Python
a * or / left invalid goes too, and a *args with keyword-only
parameters after it leaves a bare * (def f(a, *args, b) minus args
is def f(a, *, b)). One Go name of a, b int, or one name that a
destructuring parameter binds, goes alone. Refused: a name the function
lacks, and in C the last named parameter before ....
Use this when: dropping one parameter without retyping the signature. Don't use this when: rewriting the signature (replace_signature).
Example: target="LRUCache.get" parameter_name="default"
| Name | Required | Description | Default |
|---|---|---|---|
| target | Yes | Function or method name as list_symbols lists it, dotted for nesting ('LRUCache.get'); overloads take parameter types ('A.m(int)'). | |
| file_path | Yes | Absolute path to the source or config file. | |
| parameter_name | Yes | Bare name of the parameter (e.g. 'default'), without its type or default value. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations (destructiveHint=true, readOnlyHint=false) only signal that this mutates; the description adds substantial context beyond that: comments travel with a line-own parameter, `()`/`(void)` results, Python `*`/`/` cleanup, `*args` leaving a bare `*`, Go `a, b int` and destructuring singletons, and explicit refusal cases. That is exactly the edge-case behavior an agent cannot infer from annotations or schema.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with purpose, then behavior, then when/when-not, then an example — a sensible progression with no filler sentences. It is dense with parenthetical edge cases, which earns its place but could be tightened slightly; the example partially restates the schema's own field descriptions.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a destructive mutation tool, the agent knows the effect on the signature and body, the formatting-preservation rules, and the conditions under which the call is refused. An output schema exists, so return-value detail is unnecessary — nothing material is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so baseline is 3; the description goes further by clarifying what a 'name' means operationally — one name of a Go `a, b int` group, or a name bound by a destructuring parameter, is removed alone. The worked example (target="LRUCache.get", parameter_name="default") also reinforces the dotted target format.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Opens with a specific verb and resource: 'Remove a parameter by name from a function's signature, keeping the body.' The scope qualifier ('keeping the body') immediately distinguishes it from replace_signature and replace_function, so an agent can route 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.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit 'Use this when: dropping one parameter without retyping the signature' and 'Don't use this when: rewriting the signature (replace_signature)', naming the sibling alternative. Both the positive trigger and the exclusion are stated, not implied.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
replace_docstringADestructive
Replace or add the docstring of a Python function, method or class, or
of the module with target "". new_docstring must be one string literal
with its quotes; anything else (bare text, an f-string, bytes, an empty
value) is refused. A new docstring goes first in the body; the module's
goes below a #! line and encoding or header comments. A new docstring
for a body on its signature's line is refused (use
replace_function_body); so is any non-Python file.
Use this when: adding or updating a Python docstring.
Don't use this when: editing a # comment above the symbol
(edit_leading_comment).
Example: target="LRUCache.get" new_docstring='"""Return the cached value, or None."""'
| Name | Required | Description | Default |
|---|---|---|---|
| target | Yes | Python function, method or class name, dotted for nesting (e.g. 'LRUCache.get'), or '' for the module. | |
| file_path | Yes | Absolute path to the source or config file. | |
| new_docstring | Yes | One Python string literal with its quotes, usually triple-quoted. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already flag destructiveHint=true and readOnlyHint=false, and the description goes well beyond that: it enumerates refusal conditions (bare text, f-strings, bytes, empty value, non-Python files, signature-line bodies), states where the new docstring is placed in the body, and specifies module-level placement below `#!` and encoding/header comments. These are non-obvious mutation side effects an agent cannot get from the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The placement and refusal rules are front-loaded in the first paragraph, followed by the when/when-not block and a compact example – well ordered and dense. The 'Use this when: adding or updating a Python docstring' line is a light restatement of what the first paragraph already established, a small redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a three-required-parameter mutating edit tool with an output schema available, everything an agent needs to call it correctly is present: valid input form, placement semantics, refused cases, and escalation paths to sibling tools. No gaps remain that would cause a malformed or misrouted call.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
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 adds real constraints the schema does not: new_docstring must include its own quotes, f-strings and bytes are refused, and target="" means the module. The worked example anchors both arguments concretely; it stops short of describing any return or error payload shape, but the output schema covers that.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (replace/add) and a specific resource (Python docstring of a function, method, class, or module) and pins down the target addressing scheme. It actively distinguishes itself from siblings by naming replace_function_body and edit_leading_comment, so an agent can route without opening any schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Has explicit 'Use this when: adding or updating a Python docstring' and 'Don't use this when: editing a `#` comment above the symbol (edit_leading_comment)', naming the alternative tool. It also names replace_function_body as the fallback for the signature-line-body case, giving three concrete routing rules.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
replace_functionADestructive
Replace a whole symbol (decorators, signature and body) with new content.
The replaced span is what read_symbol returns: decorators, a JS/TS
export, a C++ template <...> header and code that only wraps the
symbol are part of it, so keep them in content. read_symbol's text,
edited or not, goes in as it is, and may become several members;
content written from column 0 is re-indented to the symbol's level. A
symbol that shares a line with other code has only its own text
replaced. For one name of int a, b; the content must keep the others.
Refused in JSON, YAML and TOML files (use replace_value).
Use this when: rewriting a symbol top to bottom (name, parameters and body). Don't use this when: only the body changes (replace_function_body), only the signature (replace_signature), or a few lines (replace_in_body).
Example: target="LRUCache.get" content='def get(self, key, default=None):\n return self.items.get(key, default)'
| Name | Required | Description | Default |
|---|---|---|---|
| target | Yes | Function or method name as list_symbols lists it, dotted for nesting ('LRUCache.get'); overloads take parameter types ('A.m(int)'). | |
| content | Yes | Complete new source of the symbol, decorators included, in read_symbol's shape or written from column 0. | |
| file_path | Yes | Absolute path to the source or config file. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already flag destructiveHint=true/openWorldHint=false, and the description adds real behavioral context on top: exactly what span gets replaced, re-indentation from column 0, shared-line symbols being narrowed, multi-member expansion, and the multi-declarator `int a, b;` constraint. This is the kind of edge-case disclosure a mutating tool needs.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the core action, then edge cases, then when/when-not, then an example — a sensible ordering. It runs long and a few clauses (e.g., restating that decorators stay in content) overlap with the schema, keeping it just short of ideal density.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With annotations, a full-coverage schema, and an output schema present, everything an agent needs is covered: span semantics, formatting normalization, format exclusions, and sibling routing. Nothing material is left to inference.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so baseline is high; the description still adds meaning by saying content must retain decorators/exports/template headers and may be supplied in read_symbol's exact shape, plus a concrete target/content example. It does not add much beyond the schema on `file_path`, but that parameter is self-evident.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Opens with a precise verb+resource+scope: 'Replace a whole symbol (decorators, signature and body) with new content.' That phrasing immediately distinguishes it from partial-edit siblings like replace_function_body and replace_signature, so no schema inspection is needed to tell them apart.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit 'Use this when' (rewriting a symbol top to bottom) and 'Don't use this when' with three named alternatives mapped to concrete conditions (body-only, signature-only, few lines). It also routes JSON/YAML/TOML writers to replace_value, covering a whole class of misuse.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
replace_function_bodyADestructive
Replace only the body of a function, keeping its signature and decorators. A body on its signature's line is rebuilt over lines of its own, and an empty body gets content one level deeper than the function. A Ruby method's rescue, else and ensure clauses stay and only the code before them is replaced, unless content has clauses of its own. Refused for a function without a block body: a Ruby endless method, or an arrow function whose body is an expression (use replace_function).
Use this when: changing the implementation but not the interface. Don't use this when: the parameters or return type change too (replace_function), or only a few lines change (replace_in_body).
Example: target="LRUCache.get" content='if key in self.items:\n return self.items[key]\nreturn None'
| Name | Required | Description | Default |
|---|---|---|---|
| target | Yes | Function or method name as list_symbols lists it, dotted for nesting ('LRUCache.get'); overloads take parameter types ('A.m(int)'). | |
| content | Yes | New body statements without the signature or braces, re-indented as a block to the body's indentation. | |
| file_path | Yes | Absolute path to the source or config file. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only declare destructiveHint=true/readOnlyHint=false, but the description goes far beyond: it discloses single-line body reconstruction, indentation depth for empty bodies, preservation of Ruby rescue/else/ensure clauses, and explicit refusal conditions (endless methods, expression-bodied arrow functions). This is exactly the behavioral context a caller needs before a destructive edit.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded purpose followed by well-labeled when/when-not and an example, with no filler. It is dense and multi-clause but each sentence (clauses, refusals, example) earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a destructive edit tool, it covers scope, edge cases, refusal behavior, alternatives, and an example; an output schema exists so return values need no explanation. Complete for correct invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
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 worked example clarifies the dotted nesting syntax for target and the escaped-newline literal form for content, adding practical meaning beyond the schema text.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Replace only the body of a function') plus the scope boundary ('keeping its signature and decorators'). The body-on-line, empty-body, and Ruby clause cases make the exact operation unambiguous versus replace_function and replace_in_body.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Has explicit 'Use this when' and 'Don't use this when' blocks that name both alternatives (replace_function, replace_in_body) and the exact conditions selecting each. Nothing 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.
replace_in_bodyADestructive
Replace a snippet inside a function's body; the match is scoped to that body, so text elsewhere in the file never matches. A snippet found nowhere is refused; one found in several places is refused with their line numbers: add context.
Use this when: changing one statement or block in a long body. Don't use this when: replacing the whole body (replace_function_body), or editing a sub-expression no unique snippet can locate (your normal edit tool).
Example (a block written without its indentation): target="handle" old_snippet="if retry:\n wait()" new_snippet="if retry:\n backoff()\n wait()"
| Name | Required | Description | Default |
|---|---|---|---|
| target | Yes | Function or method name as list_symbols lists it, dotted for nesting ('LRUCache.get'); overloads take parameter types ('A.m(int)'). | |
| file_path | Yes | Absolute path to the source or config file. | |
| new_snippet | Yes | Replacement text; its lines move with the match's indentation, keeping their relative indentation, and text already at the file's indentation goes in as written. '' deletes the snippet. | |
| old_snippet | Yes | Text in the target's body, matching one place: its exact text at token boundaries, or else whole lines with the same indentation added to or removed from each. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
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 real behavioral content beyond that: ambiguous matches are refused with line numbers, zero matches are refused, and new-snippet lines follow the match's indentation. It doesn't say what the refusal looks like (error vs. status), which keeps it off 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.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded purpose, then clearly labeled use/don't-use blocks and one worked example. Slightly long because of the multi-line example, but each block carries information an agent needs.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Output schema exists so return values needn't be explained, and all four params are documented in-schema. The description closes the main remaining gaps (scoping, uniqueness, refusal conditions, indentation). Only the shape of a refusal response is left implicit.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so baseline is 3. The description goes further by explaining the uniqueness requirement for old_snippet with a concrete example, including the indentation-relaxed writing style, which is the non-obvious part agents get wrong.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('replace a snippet inside a function's body') plus the scoping constraint that distinguishes it from a plain text replace. It also names the sibling it is not (replace_function_body) so an agent can route 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.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit 'Use this when' / 'Don't use this when' sections with two named alternatives: replace_function_body for whole-body replacement, and the normal edit tool for sub-expressions no unique snippet can locate. The selection condition is fully spelled out.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
replace_signatureADestructive
Replace the signature of a function, or the header of a class, keeping
its body. Existing decorators, Java annotations and a C++ template <...> header stay unless new_signature has its own. Code that
read_symbol's signature starts with (a JS/TS const f =, a closure's
key, a TS declare, a Ruby private) is replaced when new_signature
starts with it, else kept. A method without a body keeps its ;.
Refused for a symbol with no signature, such as a variable.
Use this when: changing a function's parameters, return type or name. Don't use this when: the body changes too (replace_function), or one parameter is added or removed (add_parameter, remove_parameter).
Example: target="LRUCache.get" new_signature="def get(self, key, default=None):"
| Name | Required | Description | Default |
|---|---|---|---|
| target | Yes | Function or method name as list_symbols lists it, dotted for nesting ('LRUCache.get'); overloads take parameter types ('A.m(int)'). | |
| file_path | Yes | Absolute path to the source or config file. | |
| new_signature | Yes | Everything from the start of the definition up to its body, as read_symbol(depth='signature') returns it (e.g. 'def get(self, key):', JS 'get(key, d)' without the '{'); indentation on its first line is ignored. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true and non-read-only, so the description's job is to explain the blast radius — and it does: the body is preserved, decorators/Java annotations/`template<...>` headers survive unless overridden, prefix tokens are conditionally replaced, and the operation is refused for symbols with no signature. That is materially more than the annotations convey.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the core action, then scoped by when/when-not and anchored by an example — a well-organized shape. The decorator/template preservation sentence is dense but relevant to correctness; nothing is redundant filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values need not be described. The description covers the mutation's side effects, preservation rules, and refusal cases, which is everything an agent needs to invoke this destructive edit safely.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
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. The description still adds value by clarifying how new_signature interacts with the existing signature (prefix kept vs. replaced) and by giving a concrete target/new_signature example, though it does not restate the dotted-nesting target format.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('replace the signature of a function, or the header of a class, keeping its body'), which is precise enough to distinguish it from replace_function and replace_function_body without opening either schema. The refusal condition ('symbol with no signature, such as a variable') further narrows the scope.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit 'Use this when' (parameter/return type/name changes) and 'Don't use this when' clauses name the exact alternatives — replace_function for body changes, add_parameter/remove_parameter for single-parameter edits. The routing decision is fully determined.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
replace_valueADestructive
Replace the value of an existing config key, dict or object entry, or
of a variable, constant, field or macro in a source file (X = 1,
const X = 1;, int x = 1;, #define N 3). Only the value changes; a
declaration without one gets one (let x; becomes let x = 2;, YAML
a: becomes a: 2). Refused: a function, class or type (use
replace_function), a name sharing one value with others (a = b = 1)
and a declaration that cannot have a value (extern, TS declare).
Array elements are not addressable.
Use this when: updating a value that exists. Don't use this when: the key is new (add_key), or you edit an array (append_to_array, remove_from_array).
Example: target="project.version" content='"2.0.0"'
| Name | Required | Description | Default |
|---|---|---|---|
| target | Yes | Key path from the top level in a config file ('project.version'; quote a key with dots, '"editor.fontSize"'; keys in YAML flow mappings and TOML inline tables count, 'a.x'), a path into a Python or JS/TS module-level dict or object ('CONFIG."timeout"', 'CONFIG.server.port'), or a variable, constant, field or macro name ('MAX', 'A.x'). | |
| content | Yes | Value as source text in the file's syntax, strings quoted (e.g. '"2.0.0"' or '42'). | |
| file_path | Yes | Absolute path to the source or config file. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes well beyond the annotations (destructiveHint=true, readOnlyHint=false) by disclosing exactly what mutates: only the value changes, and a declaration lacking a value gains one (`let x;` -> `let x = 2;`, YAML `a:` -> `a: 2`). It also lists three hard refusal conditions (chained `a = b = 1`, `extern`, TS `declare`) and states array elements are not addressable. Output schema exists, so return format need not be repeated.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the core action, then structured into use/don't-use blocks and an example. Despite the length, every sentence contributes either routing, a refusal boundary, or a semantic detail; there is no padding.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 3-parameter destructive write tool with an output schema and full annotation coverage, the description supplies everything an agent needs: scope, refusal cases, sibling routing, and a worked example. No material gap remains.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3; the description adds value by showing a concrete target/content pair (target="project.version", content='"2.0.0"'), which conveys that content must be quoted source text in the file's syntax — a common failure point. It stops short of explaining the target path grammar in depth, which is left to the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (Replace) and resource (value of an existing config key, dict/object entry, variable, constant, field or macro), then enumerates concrete syntax forms (`X = 1`, `const X = 1;`, `#define N 3`). It also names what it explicitly is not (replace_function) and what is out of scope (array elements), so an agent can place it among the 29 siblings immediately.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Has explicit 'Use this when: updating a value that exists' and 'Don't use this when: the key is new (add_key), or you edit an array (append_to_array, remove_from_array)' sections naming the exact alternatives. The refusal list adds further routing (function/class/type -> replace_function). Nothing 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.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
28 tool updates
v3.2.0- Changed
add_field3 fields changed- added
Input schema / properties / class_target / descriptionAdded value: +"Class name as list_symbols lists it (a struct, interface or Go struct type too), dotted for nesting ('A.B')." - added
Input schema / properties / content / descriptionAdded value: +"Field or member declaration as source text (e.g. 'version = \"1.0\"' or Go 'version int')." - added
Input schema / properties / file_path / descriptionAdded value: +"Absolute path to the source or config file."
- Changed
add_import2 fields changed- added
Input schema / properties / file_path / descriptionAdded value: +"Absolute path to the source or config file." - added
Input schema / properties / import_text / descriptionAdded value: +"Complete import line in the file's language (e.g. 'import os', '#include <stdlib.h>'); in Go a bare spec ('\"fmt\"') works too."
- Changed
add_import_name3 fields changed- added
Input schema / properties / file_path / descriptionAdded value: +"Absolute path to the source or config file." - added
Input schema / properties / module / descriptionAdded value: +"Module of the import as written, without quotes (e.g. 'typing' or './utils')." - added
Input schema / properties / name / descriptionAdded value: +"One imported name, e.g. 'Optional'."
- Changed
add_key4 fields changed- added
Input schema / properties / file_path / descriptionAdded value: +"Absolute path to the source or config file." - added
Input schema / properties / key / descriptionAdded value: +"Key to add. JSON, YAML and JS/TS: one name, quoted for you when needed. TOML: a dotted key, so quote a name with a dot yourself ('\"example.com\"'). Python: a key expression, so quote string keys ('\"timeout\"')." - added
Input schema / properties / parent_target / descriptionAdded value: +"Parent container: its key path from the top level in a config file ('' for the root; quote a key with dots, 'a.\"b.c\"'), or a Python or JS/TS module-level variable's name, dotted into nested literals ('CONFIG.server')." - added
Input schema / properties / value / descriptionAdded value: +"Value as source text in the file's syntax, strings quoted (e.g. '\"2.0.0\"' or '42')."
- Changed
add_method3 fields changed- added
Input schema / properties / class_target / descriptionAdded value: +"Class name as list_symbols lists it (a struct, interface or Go struct type too), dotted for nesting ('A.B')." - added
Input schema / properties / content / descriptionAdded value: +"Complete method source, re-indented like the class's members, keeping its own relative indentation." - added
Input schema / properties / file_path / descriptionAdded value: +"Absolute path to the source or config file."
- Changed
add_parameter4 fields changed- added
Input schema / properties / file_path / descriptionAdded value: +"Absolute path to the source or config file." - added
Input schema / properties / parameter / descriptionAdded value: +"Source text of one parameter (e.g. 'default=None', 'const int* buf'); the comma is added for you." - added
Input schema / properties / position / descriptionAdded value: +"'end' (default) after the last parameter, before any that must stay last; 'start' before the first. Other values are refused." - added
Input schema / properties / target / descriptionAdded value: +"Function or method name as list_symbols lists it, dotted for nesting ('LRUCache.get'); overloads take parameter types ('A.m(int)')."
- Changed
add_top_level3 fields changed- added
Input schema / properties / content / descriptionAdded value: +"Top-level code, inserted as written; read_symbol's text of a nested symbol is moved to column 0 as a whole." - added
Input schema / properties / file_path / descriptionAdded value: +"Absolute path to the source or config file." - added
Input schema / properties / position / descriptionAdded value: +"'bottom' (default) at the end of the file; 'top' after the preamble (package clause, `#!` and magic comments, module docstring, directives such as 'use strict', imports and includes). Other values are refused."
- Changed
append_to_array3 fields changed- added
Input schema / properties / file_path / descriptionAdded value: +"Absolute path to the source or config file." - added
Input schema / properties / target / descriptionAdded value: +"Key path from the top level to a JSON, YAML or TOML array ('project.dependencies'), or a Python module-level list's name." - added
Input schema / properties / value / descriptionAdded value: +"Value as source text in the file's syntax, strings quoted (e.g. '\"2.0.0\"' or '42')."
- Changed
delete_in_body3 fields changed- added
Input schema / properties / file_path / descriptionAdded value: +"Absolute path to the source or config file." - added
Input schema / properties / snippet / descriptionAdded value: +"Text in the target's body, matching one place: its exact text at token boundaries, or else whole lines with the same indentation added to or removed from each." - added
Input schema / properties / target / descriptionAdded value: +"Function or method name as list_symbols lists it, dotted for nesting ('LRUCache.get'); overloads take parameter types ('A.m(int)')."
- Changed
delete_key2 fields changed- added
Input schema / properties / file_path / descriptionAdded value: +"Absolute path to the source or config file." - added
Input schema / properties / target / descriptionAdded value: +"Key path from the top level in a config file ('dependencies.tree-sitter'; quote a key with dots, '\"editor.fontSize\"'), or a path into a Python or JS/TS module-level dict or object ('CONFIG.\"timeout\"', 'CONFIG.server.port')."
- Changed
delete_symbol3 fields changed- added
Input schema / properties / file_path / descriptionAdded value: +"Absolute path to the source or config file." - added
Input schema / properties / include_leading_comments / descriptionAdded value: +"True (default) also deletes the comment block above the symbol, or before it on its first line; false keeps it." - added
Input schema / properties / target / descriptionAdded value: +"Symbol name as list_symbols lists it, dotted for nesting (e.g. 'LRUCache.old_method', 'A.m(int)')."
- Changed
edit_leading_comment4 fields changed- added
Input schema / properties / comment / descriptionAdded value: +"Comment text with its markers ('# note', '// note', '/** ... */'); required for 'add' and 'replace', ignored for 'remove'." - added
Input schema / properties / file_path / descriptionAdded value: +"Absolute path to the source or config file." - added
Input schema / properties / op / descriptionAdded value: +"'add' inserts a comment, refused when the symbol has one (the error quotes it: use 'replace' with a block that repeats lines to keep, such as lint directives); 'replace' replaces the block, or adds one; 'remove' deletes it. Other values are refused." - added
Input schema / properties / target / descriptionAdded value: +"Symbol name as list_symbols lists it, dotted for nesting ('LRUCache.get'), or a YAML/TOML key path from the top level or TOML [table] name ('tool.uv')."
- Changed
find_references2 fields changed- added
Input schema / properties / file_path / descriptionAdded value: +"Absolute path to the source or config file." - added
Input schema / properties / target / descriptionAdded value: +"Identifier to find, a plain name, not a dotted path (e.g. 'LRUCache')."
- Changed
insert_in_body6 fields changed- added
Input schema / properties / after / descriptionAdded value: +"Anchor in the body to insert after; '' (default) leaves this mode unused." - added
Input schema / properties / at / descriptionAdded value: +"'top' or 'bottom' of the body; '' (default) leaves this mode unused. Other values are refused." - added
Input schema / properties / before / descriptionAdded value: +"Anchor in the body to insert before; '' (default) leaves this mode unused." - added
Input schema / properties / file_path / descriptionAdded value: +"Absolute path to the source or config file." - added
Input schema / properties / new_snippet / descriptionAdded value: +"Text to insert. With at, re-indented as a block to the body's indentation; with after or before, indented like the anchor (as written when already at the file's indentation there)." - added
Input schema / properties / target / descriptionAdded value: +"Function or method name as list_symbols lists it, dotted for nesting ('LRUCache.get'); overloads take parameter types ('A.m(int)')."
- Changed
insert_sibling4 fields changed- added
Input schema / properties / content / descriptionAdded value: +"Code to insert, re-indented to the target's level (in tabs where the file indents with them); read_symbol's text goes in as a whole." - added
Input schema / properties / file_path / descriptionAdded value: +"Absolute path to the source or config file." - added
Input schema / properties / position / descriptionAdded value: +"'before' or 'after' the target; other values are refused." - added
Input schema / properties / target / descriptionAdded value: +"Symbol name as list_symbols lists it, dotted for nesting (e.g. 'LRUCache', 'A.m')."
- Changed
list_symbols1 field changed- added
Input schema / properties / file_path / descriptionAdded value: +"Absolute path to the source or config file."
- Changed
read_imports1 field changed- added
Input schema / properties / file_path / descriptionAdded value: +"Absolute path to the source or config file."
- Changed
read_symbol3 fields changed- added
Input schema / properties / depth / descriptionAdded value: +"'full' (default) the whole symbol; 'interface' a class skeleton or function signature; 'signature' the signature or class header. Config files take only 'full'. Other values are refused." - added
Input schema / properties / file_path / descriptionAdded value: +"Absolute path to the source or config file." - added
Input schema / properties / target / descriptionAdded value: +"Symbol name as list_symbols lists it, dotted for nesting ('LRUCache.get', 'A.m(int)'), or a config key path from the top level ('project.version'; quote a key with dots, '\"editor.fontSize\"')."
- Changed
remove_from_array3 fields changed- added
Input schema / properties / file_path / descriptionAdded value: +"Absolute path to the source or config file." - added
Input schema / properties / target / descriptionAdded value: +"Key path from the top level to a JSON, YAML or TOML array ('project.dependencies'), or a Python module-level list's name." - added
Input schema / properties / value_match / descriptionAdded value: +"Element to remove, compared with each element's source text, whitespace stripped (e.g. '\"old-package\"')."
- Changed
remove_import2 fields changed- added
Input schema / properties / file_path / descriptionAdded value: +"Absolute path to the source or config file." - added
Input schema / properties / import_text / descriptionAdded value: +"Exact import line to remove (e.g. 'import os')."
- Changed
remove_import_name3 fields changed- added
Input schema / properties / file_path / descriptionAdded value: +"Absolute path to the source or config file." - added
Input schema / properties / module / descriptionAdded value: +"Module of the import as written, without quotes (e.g. 'typing' or './utils')." - added
Input schema / properties / name / descriptionAdded value: +"One imported name, e.g. 'Optional'."
- Changed
remove_parameter3 fields changed- added
Input schema / properties / file_path / descriptionAdded value: +"Absolute path to the source or config file." - added
Input schema / properties / parameter_name / descriptionAdded value: +"Bare name of the parameter (e.g. 'default'), without its type or default value." - added
Input schema / properties / target / descriptionAdded value: +"Function or method name as list_symbols lists it, dotted for nesting ('LRUCache.get'); overloads take parameter types ('A.m(int)')."
- Changed
replace_docstring3 fields changed- added
Input schema / properties / file_path / descriptionAdded value: +"Absolute path to the source or config file." - added
Input schema / properties / new_docstring / descriptionAdded value: +"One Python string literal with its quotes, usually triple-quoted." - added
Input schema / properties / target / descriptionAdded value: +"Python function, method or class name, dotted for nesting (e.g. 'LRUCache.get'), or '' for the module."
- Changed
replace_function3 fields changed- added
Input schema / properties / content / descriptionAdded value: +"Complete new source of the symbol, decorators included, in read_symbol's shape or written from column 0." - added
Input schema / properties / file_path / descriptionAdded value: +"Absolute path to the source or config file." - added
Input schema / properties / target / descriptionAdded value: +"Function or method name as list_symbols lists it, dotted for nesting ('LRUCache.get'); overloads take parameter types ('A.m(int)')."
- Changed
replace_function_body3 fields changed- added
Input schema / properties / content / descriptionAdded value: +"New body statements without the signature or braces, re-indented as a block to the body's indentation." - added
Input schema / properties / file_path / descriptionAdded value: +"Absolute path to the source or config file." - added
Input schema / properties / target / descriptionAdded value: +"Function or method name as list_symbols lists it, dotted for nesting ('LRUCache.get'); overloads take parameter types ('A.m(int)')."
- Changed
replace_in_body4 fields changed- added
Input schema / properties / file_path / descriptionAdded value: +"Absolute path to the source or config file." - added
Input schema / properties / new_snippet / descriptionAdded value: +"Replacement text; its lines move with the match's indentation, keeping their relative indentation, and text already at the file's indentation goes in as written. '' deletes the snippet." - added
Input schema / properties / old_snippet / descriptionAdded value: +"Text in the target's body, matching one place: its exact text at token boundaries, or else whole lines with the same indentation added to or removed from each." - added
Input schema / properties / target / descriptionAdded value: +"Function or method name as list_symbols lists it, dotted for nesting ('LRUCache.get'); overloads take parameter types ('A.m(int)')."
- Changed
replace_signature3 fields changed- added
Input schema / properties / file_path / descriptionAdded value: +"Absolute path to the source or config file." - added
Input schema / properties / new_signature / descriptionAdded value: +"Everything from the start of the definition up to its body, as read_symbol(depth='signature') returns it (e.g. 'def get(self, key):', JS 'get(key, d)' without the '{'); indentation on its first line is ignored." - added
Input schema / properties / target / descriptionAdded value: +"Function or method name as list_symbols lists it, dotted for nesting ('LRUCache.get'); overloads take parameter types ('A.m(int)')."
- Changed
replace_value3 fields changed- added
Input schema / properties / content / descriptionAdded value: +"Value as source text in the file's syntax, strings quoted (e.g. '\"2.0.0\"' or '42')." - added
Input schema / properties / file_path / descriptionAdded value: +"Absolute path to the source or config file." - added
Input schema / properties / target / descriptionAdded value: +"Key path from the top level in a config file ('project.version'; quote a key with dots, '\"editor.fontSize\"'; keys in YAML flow mappings and TOML inline tables count, 'a.x'), a path into a Python or JS/TS module-level dict or object ('CONFIG.\"timeout\"', 'CONFIG.server.port'), or a variable, constant, field or macro name ('MAX', 'A.x')."
17 tool updates
v2.10.0- Removed
add_comment_before - Changed
add_top_level1 field changed- added
Input schema / properties / positionAdded value: +{ + "default": "bottom", + "title": "Position", + "type": "string" +}
- Removed
append_to_body - Added
delete_in_body - Changed
delete_symbol1 field changed- added
Input schema / properties / include_leading_commentsAdded value: +{ + "default": true, + "title": "Include Leading Comments", + "type": "boolean" +}
- Added
edit_leading_comment - Removed
get_signature - Removed
insert_after - Removed
insert_before - Added
insert_in_body - Added
insert_sibling - Removed
prepend_to_body - Removed
read_interface - Changed
read_symbol1 field changed- added
Input schema / properties / depthAdded value: +{ + "default": "full", + "title": "Depth", + "type": "string" +}
- Removed
remove_leading_comment - Added
replace_in_body - Removed
replace_leading_comment
32 tool updates
v1.2.0- First observed
add_comment_before - First observed
add_field - First observed
add_import - First observed
add_import_name - First observed
add_key - First observed
add_method - First observed
add_parameter - First observed
add_top_level - First observed
append_to_array - First observed
append_to_body - First observed
delete_key - First observed
delete_symbol - First observed
find_references - First observed
get_signature - First observed
insert_after - First observed
insert_before - First observed
list_symbols - First observed
prepend_to_body - First observed
read_imports - First observed
read_interface - First observed
read_symbol - First observed
remove_from_array - First observed
remove_import - First observed
remove_import_name - First observed
remove_leading_comment - First observed
remove_parameter - First observed
replace_docstring - First observed
replace_function - First observed
replace_function_body - First observed
replace_leading_comment - First observed
replace_signature - First observed
replace_value
TDQS
Scored across 28 tools
Most tools target distinct operations, and the descriptions provide explicit “Use this when / Don’t use this when” guidance to separate close neighbors like replace_function, replace_function_body, and replace_in_body. The remaining ambiguity comes from the large number of fine-grained edit tools, where an agent must carefully choose between body, signature, parameter, sibling, and top-level variants.
Names are consistently snake_case and verb-first, following predictable patterns such as add_import, remove_import_name, replace_signature, and list_symbols. The minor inconsistency is the mixed use of delete and remove for deletion operations, though the names remain readable and mostly predictable.
With 28 tools, the surface is heavy and requires agents to select among many highly granular operations. The domain is complex, but several tools could plausibly be consolidated or grouped under operation-based interfaces to reduce selection burden.
The server covers a strong lifecycle for imports, symbols, bodies, signatures, parameters, comments, docstrings, and config keys/arrays. Notable gaps remain around higher-level refactors such as rename-across-file or moving symbols, but agents can work around these by combining find_references and copy/delete operations.
Maintenance
Related MCP Connectors
A comprehensive Model Context Protocol (MCP) server that enables AI assistants to interact with yo…
Nifty's MCP server — exposes tasks, projects, messages, and files as tools for AI agents.
A Model Context Protocol server for Wix AI tools
Model Context Protocol server for the Apideck Unified API. Connect any MCP-compatible agent framework to 100+ accounting systems, HRIS platforms, file storage providers, and more through one integration. More information https://www.apideck.com/mcp-server
Related MCP Servers
- AlicenseBqualityFmaintenanceA Model Context Protocol (MCP) server that provides code analysis capabilities using tree-sitter, designed to give Claude intelligent access to codebases with appropriate context management.26532 PyPI309MIT
- AlicenseAqualityCmaintenanceA Model Context Protocol (MCP) server that helps large language models index, search, and analyze code repositories with minimal setup22142,023 PyPI1,007MIT
- AlicenseAqualityDmaintenanceA Model Context Protocol (MCP) server designed to easily dump your codebase context into Large Language Models (LLMs).14 npm3Apache 2.0

CodeAlive MCPofficial
AlicenseNot gradedqualityBmaintenanceA Model Context Protocol server that enhances AI agents by providing deep semantic understanding of codebases, enabling more intelligent interactions through advanced code search and contextual awareness.90MIT