filekeeper-mcp
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@filekeeper-mcpReplace every TODO with DONE in notes.md and let me undo it"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Filekeeper
Safe, predictable filesystem operations for humans, shell scripts and AI agents.
One Core library, a keeper command line, and an MCP server that all behave
identically because they call the same code.
Filekeeper confines every operation to a registered workspace, replaces whole files atomically, refuses credential-shaped write targets, and reports structured results with stable error codes.
Status
Version 0.1 is the foundation, operations and reversibility release. It includes workspace registration and confinement, read/info/hash/list/search, file and directory create/copy/move/delete, atomic whole-file replacement, text detection and size limits, durable operation history with content-addressed blobs, safe undo with conflict detection, staged literal text editing, line-range editing, unified-diff application, the CLI, and the MCP server.
Not in this release, and deliberately so:
redo (undo is the requirement; redo is convenience) — an undone operation is recorded, but
redoitself is not implementedexplicit snapshots and restore (history blobs already hold the data)
advisory locks with TTL (the tables exist; the API does not)
batch execution, file watching, archives, history pruning UI, HTTP transport
Related MCP server: axiom
Install
uv tool install filekeeper-cli # or: pip install filekeeper-cli
keeper --helpThe published filekeeper-cli distribution has no
third-party dependencies; it installs the filekeeper import package and the
keeper console script. The MCP server is a separate distribution, so
installing the CLI never pulls in the MCP SDK:
uv tool install filekeeper-mcp # or: pip install filekeeper-mcp
filekeeper-mcp --root ~/projectThe two names are not interchangeable: pip install filekeeper-cli (or
uv add filekeeper-cli) installs the library and the keeper CLI only, while
pip install filekeeper-mcp (or uv add filekeeper-mcp) installs the MCP
server and pulls the CLI in as its dependency.
Quick start
keeper init # create the home directory and database
keeper workspace create notes ~/notes # register a workspace
keeper workspace use notes # make it the default
keeper file create todo.md --content "# Todo\n"
keeper file read todo.md
keeper file write todo.md --content "# Todo\n- write tests\n"
keeper file list . --recursive --glob '*.md'Every command accepts --json for machine-readable output and --workspace NAME
or --root PATH to select a workspace. Selection precedence is explicit
--workspace, then explicit --root, then the configured default; Filekeeper
never guesses when several workspaces exist.
MCP server
filekeeper-mcp speaks the Model Context Protocol over STDIO. It is a thin
adapter over Core: no filesystem behaviour lives in it, so a guarded write or a
refusal is identical whichever adapter issued it.
filekeeper-mcp --workspace notes
filekeeper-mcp --root ~/work/tree --home ~/.local/share/filekeeper--workspace and --root are mutually exclusive; --home overrides
FILEKEEPER_HOME; --log-level controls stderr only, because stdout carries
protocol messages. --actor and --task-id are optional audit metadata recorded
on every mutation. There is no network listener in this release.
The allowed roots come from start-up configuration only. No tool argument can widen them, register a workspace or point the server at another tree.
Tools
Read-only: workspace_list, workspace_info, file_read, file_read_many,
directory_list, file_info, file_search, content_search, history_list,
history_get, history_diff.
Mutating: file_create, file_write, file_copy, file_move, file_delete,
directory_create, directory_delete, file_replace_text,
file_replace_lines, file_insert_lines, file_delete_lines,
file_apply_patch, undo_operation, undo_last.
The same conventions apply as in the CLI: workspace-relative paths, 1-based
inclusive line numbers, expected_hash / expected_content guards, dry_run on
every mutation, and operation_id / undo_available on every mutation. Each
tool's description states its own semantics, and each carries protocol
annotations (readOnlyHint, destructiveHint, idempotentHint,
openWorldHint) that describe what it actually does.
Requests that could exhaust memory are refused with LIMIT_EXCEEDED, not
truncated: 32 paths per file_read_many, a 1 MiB patch, and at most 200 search
results, 1000 directory entries or 200 history entries per request. Errors are
structured data in the same envelope the CLI uses: ok plus error, carrying the
stable Core code, retryable, and details (including the caller's own path),
with no stack trace and no host path.
A tool that mutates returns the Core operation_id and undo_available exactly
as the CLI does, so history_list, history_diff and undo_operation work the
same way from an agent host. The optional audit field is task_id; it is
supplied by server configuration rather than trusted from a tool argument.
Where state lives
Project-local by default. A workspace's own state — the operation journal and
content-addressed blobs — lives in <workspace>/.filekeeper/, created on the
first mutation that needs it. It travels with the checkout, so a fresh clone does
not silently lose undo history, and deleting a project takes its blobs with it.
Workspace registrations live in the Filekeeper home directory
(~/.local/share/filekeeper on Linux, or FILEKEEPER_HOME), because a registry
of many roots cannot live inside one of them.
Set state_location = "global" in config.toml to keep one shared store under the
home directory instead. The trade-off: history survives deleting the checkout, but
per-project attribution and pruning become harder, and undo history no longer
travels with the tree.
If the workspace root cannot host .filekeeper/ — a read-only checkout, or a root
at / — Filekeeper falls back to the global store and says so in the response.
keeper init writes the setting only as a commented example, so that fallback
stays available; uncomment the key to pin the choice, and a project-local choice
then fails loudly instead of being redirected.
If the workspace is a git repository, Filekeeper adds .filekeeper/ to
.gitignore when it creates the state directory. Outside a repository it writes
nothing.
Reported paths when the root is /. Result paths are normally
workspace-relative, so they are the same whichever tree holds them. With a root
of / that form is indistinguishable from a repository-relative path, so every
reported path keeps its leading / and is exactly the absolute path: read
results, file_info, file_read_many entries, search results, directory
listings, copy/move result paths, and history target and item paths. Every other
root is unchanged, byte for byte. History rows are stored relative and rendered
when read, so existing records display correctly without a migration. Error
envelopes do not change.
Durability guarantees, in plain words
One file, replaced at a time, is atomic. A whole-file write goes to a temporary file in the same directory, is flushed and fsynced, then renamed over the destination. If the process dies or the disk fills before the rename, the file still holds its complete previous content. Never a truncated file, never a half-written mix.
Multiple files are recoverable, not atomic. Copy, move and recursive directory deletion affect more than one path as a sequence of individually safe steps. A crash between steps leaves some paths changed and others not. History makes the whole operation recoverable: a crash leaves a pending record, the next run resolves it honestly, and
keeper history undocan put the previous bytes back. It is still not all-or-nothing, and you should not treat a batch of changes as a transaction.The order is fixed. Before anything is touched, the previous and new contents are written and fsynced as immutable blobs, then a pending operation record is committed with SQLite in full-synchronous mode. Only then is the file replaced, verified, and the operation marked committed.
History has a size cap. A file above
max_history_blob_bytes(4 MiB by default) is still recorded, but its bytes are not stored: the result says history was skipped for it andundo_availableis false. One large edit cannot silently fill the store.
Line numbers
Line numbers are 1-based and inclusive everywhere: Core, CLI, JSON output, and
tests. --from-line 10 --to-line 20 returns lines 10 through 20, both included.
Ranges beyond the end of the file are rejected rather than silently clamped.
Editing
Every edit goes through the same journal sequence as a whole-file write: blobs,
pending record, atomic replacement, commit. Each application therefore returns a
real operation_id and is undoable with keeper history undo.
Literal text replacement
keeper file replace-text PATH --old TEXT --new TEXT (--first | --all)
This is the primary edit. Matching is staged, and the result always names the stage that matched:
exact— the literal text appears exactly as given;normalised— indentation and trailing whitespace are tolerated, and the replacement takes the indentation of the line it replaces. A stage-2 match is never applied silently;none— no match: the command fails withNO_MATCHand the nearest line numbers and their text.
The policy is explicit: --first or --all. match_count reports how many
matches were found. --expected-match-count N refuses a different count, and
--expected-content TEXT guards the exact text of a single target region.
--expected-hash guards the whole file. --dry-run prints a unified diff and
writes nothing. Replacement is always literal: the search and replacement text
are never interpreted as a regular expression or a regex template.
Line ranges
keeper file replace-lines PATH --start N --end M --replacement TEXT
keeper file insert-lines PATH --position before|after|end [--line N] --content TEXT
keeper file delete-lines PATH --start N --end MLine numbers are 1-based and inclusive. Out-of-range references are rejected,
never clamped. End-of-file insertion is the explicit --position end; it never
overloads a line number. The file's newline convention and byte-order mark are
preserved, and the same hash/content guards and dry-run apply.
Unified diffs
keeper file apply-patch [PATCH] reads a patch file, or patch text from standard
input. The whole patch is parsed and every hunk is checked against its file
before anything is written. A failed or ambiguous hunk rejects the patch; no
partial patch is applied silently. --dry-run validates and reports every file
and hunk without touching the tree. The result carries per-file and per-hunk
status, and --json carries the same data.
A multi-file patch is recorded as one logical operation, and undo restores every file. Application itself is recoverable, not atomic across files: if a later file fails after earlier ones were written, the written files are rolled back to their pre-patch bytes and the failure names what was restored. A crash is resolved from the pending journal record, never from an all-or-nothing commit.
When a hunk's header and its body disagree — the hunk is cut short or a line
prefix is not , + or - — the PATCH_FAILED error states the counts the
header declares and the counts the body actually supplied, in the message and in
details.expected_old_lines, expected_new_lines, actual_old_lines and
actual_new_lines. The existing line and reason fields are still there. Patch
text is never echoed into the error.
Commands
keeper init
keeper workspace create NAME ROOT
keeper workspace list | show NAME | use NAME | remove NAME
keeper file read PATH [--from-line N] [--to-line M] [--max-bytes N] [--encoding E]
keeper file read-many PATH... [--from-line N] [--to-line M] [--max-bytes-per-file N]
keeper file info PATH
keeper file hash PATH
keeper file exists PATH
keeper file list [PATH] [--recursive] [--glob PATTERN] [--max-entries N]
keeper file search PATH GLOB [--max-results N] # find paths
keeper file grep PATH QUERY [--regex] [--glob PATTERN] [--ignore-case]
keeper file create PATH (--content TEXT | --input FILE | stdin) [--allow-existing] [--dry-run]
keeper file write PATH (--content TEXT | --input FILE | stdin) [--expected-hash HASH] [--dry-run]
keeper file copy SOURCE DESTINATION [--expected-destination-hash HASH] [--dry-run]
keeper file move SOURCE DESTINATION [--overwrite] [--dry-run]
keeper file delete PATH [--expected-hash HASH] [--dry-run]
keeper file replace-text PATH --old TEXT --new TEXT (--first | --all) [guards] [--dry-run]
keeper file replace-lines PATH --start N --end M --replacement TEXT [guards] [--dry-run]
keeper file insert-lines PATH --position before|after|end [--line N] --content TEXT [guards] [--dry-run]
keeper file delete-lines PATH --start N --end M [guards] [--dry-run]
keeper file apply-patch [PATCH] [--dry-run]
keeper dir create PATH [--parents] [--dry-run]
keeper dir move SOURCE DESTINATION [--dry-run]
keeper dir delete PATH [--recursive --confirm-recursive] [--dry-run]
keeper history list [--path PATH] [--actor NAME] [--task-id ID] [--limit N]
keeper history show OPERATION_ID
keeper history diff OPERATION_ID
keeper history undo OPERATION_ID
keeper history undo-last [--actor NAME]Global options: --workspace NAME, --root PATH, --json, --quiet,
--verbose, --home PATH, --actor NAME, --task-id ID.
--actor and --task-id are recorded with a mutation and act as filters for
history list; they are optional and carry no host-specific meaning.
History and undo
Every mutation is recorded as an operation with its affected paths, before and
after content hashes, file modes, existence on both sides, a timestamp, and the
optional actor / task_id. Blob content is content-addressed, so identical
content is stored once.
keeper history list # newest first, this workspace only
keeper history show op_1a2b3c4d # operation, status and per-path hashes
keeper history diff op_1a2b3c4d # unified diff, never the whole file body
keeper history undo op_1a2b3c4d # restore the state before that operation
keeper history undo-last # the most recent undoable operation hereUndo is safe, not best-effort. Before changing anything it compares every affected path with the state the operation recorded:
if the path still matches the recorded after state, undo restores the recorded before bytes;
if it already matches the before state of an operation that never committed (a partially applied multi-file operation), undo leaves it alone;
if a committed operation's path no longer matches the after state — edited, deleted, or renamed away — the undo is refused with
UNDO_CONFLICT(exit codeand nothing is modified.
Undoing a create removes the file only while it still matches what was created.
Undoing a delete restores the file only while the destination is still absent.
Undoing a move checks both ends. A directory operation validates every path in
the tree first. undo-last only ever looks at the selected workspace.
The undo is itself recorded as an operation, so history list remains a
truthful ledger. Redo is deferred — it is not half-implemented; undoing an
undo is the supported way to go forward again.
A copy or a move records the path it read from in the operation's metadata
under source_path, and its summary names both ends. target_path keeps its
meaning — the path the operation targets — so existing readers are unaffected.
A refused undo is recorded too: the ledger gains an undo_refused row with the
target path, the conflict code, and the paths that blocked the undo. It changed
nothing, so it carries no items, is never offered as undoable, and undo-last
skips it. A refusal of a refusal is the one exception: undoing that
undo_refused row is refused with the same coded error, but writes no second row,
because the existing row already states the conflict. Every recorded path is
workspace-relative, never a resolved host path.
keeper file read writes file content to standard output unchanged (line endings
included). Metadata goes to stderr, or into the JSON object with --json.
--input FILE reads replacement content from a file, avoiding shell argument
limits; with neither flag, content is read from standard input when it is not a
terminal.
JSON output
Every command returns one object. Success carries "ok": true and the result
fields:
{
"ok": true,
"workspace": "notes",
"path": "todo.md",
"changed": true,
"before_hash": "sha256:...",
"after_hash": "sha256:...",
"summary": "Wrote todo.md.",
"operation_id": "op_1a2b3c4d5e6f7a8b",
"undo_available": true,
"dry_run": false,
"warnings": [],
"items": [{"path": "todo.md", "change": "modified", "before_hash": "sha256:...", "after_hash": "sha256:..."}]
}Failure carries a structured error and no traceback:
{
"ok": false,
"error": {
"code": "CONTENT_CONFLICT",
"message": "file content changed since it was read; refusing to overwrite",
"retryable": false,
"details": {
"path": "todo.md",
"expected_hash": "sha256:...",
"actual_hash": "sha256:...",
"recovery": "re-read the target, then retry against its current hash"
}
}
}Response shape. Every document — success or failure, CLI or MCP — is one
object whose first field is ok. A success document is flat: the Core result
fields sit directly beside ok. A failure document has exactly two top-level
fields, ok and error, and error has exactly code, message, retryable
and details; nothing is duplicated at the top level. The caller's own path is
in error.details.path, and details.recovery states how to proceed where a
retry is meaningful. retryable describes the identical request: a stale hash
is false, because the same call will fail the same way until the caller
re-reads the file and writes against its new hash.
operation_id is null only for a dry run (nothing was recorded).
undo_available is false when an affected file was above the history size cap,
so its previous bytes were deliberately not stored; history_skipped then names
the paths.
A dry run reports a preview, not a write. With "dry_run": true, changed is
false, operation_id and after_hash are null, and each item's after_hash
and size_bytes are null: nothing was observed, so nothing is claimed. The hash
a real run would produce appears as predicted_after_hash — a prediction, never an
observation — and would_change says whether a real run would alter anything.
before_hash and preview_diff are kept, because they describe the state the
preview was computed against. The same shape applies to every mutating command and
to the MCP tools that mirror them. A committed operation still reports
"changed": true with its observed after_hash.
changed and would_change answer different questions: would_change asks
whether the bytes would differ, while changed records whether an operation
executed and was journalled — so a real write of identical content reports
"changed": true and adds a history row, which callers may rely on as proof a
write completed. In a preview the two cannot disagree: when would_change is
false, every item reports "unchanged".
Editing results add match_stage and match_count (text replacement),
preview_diff (dry run), and, for patches, patch_files with per-hunk status.
A failure that was rolled back reports the restored paths in the error details.
Exit codes
Code | Meaning |
0 | success |
1 | unexpected error |
2 | invalid arguments or validation error |
3 | path, workspace or recorded operation not found |
4 | permission or workspace-boundary violation |
5 | concurrency conflict: stale expected hash, no matching text, or a match count other than the expected one |
6 | absolute path resolves outside the workspace |
7 | patch could not be applied; the pre-patch state is intact |
8 | a failed patch could not be fully rolled back |
9 | storage or database error |
10 | write refused: the target looks like credential material |
11 | symlink target resolves outside the workspace |
12 | undo refused: a path changed after the operation |
13 | history needed for restore is missing, corrupt or was skipped |
keeper file exists exits 3 when the path does not exist, which makes it usable as
a shell predicate.
Error codes
INVALID_ARGUMENT, PATH_NOT_FOUND, NOT_A_FILE, NOT_A_DIRECTORY,
PATH_OUTSIDE_WORKSPACE, ABSOLUTE_PATH_OUTSIDE_WORKSPACE,
SYMLINK_ESCAPE_REFUSED, PATH_IS_STATE_PATH, SYMLINK_WRITE_REFUSED,
SPECIAL_FILE_REFUSED, SENSITIVE_PATH_REFUSED, ALREADY_EXISTS,
CONTENT_CONFLICT, NO_MATCH, MATCH_COUNT_MISMATCH, PATCH_FAILED,
PARTIAL_RECOVERY, BINARY_CONTENT_REFUSED, LIMIT_EXCEEDED,
INVALID_PATTERN, WORKSPACE_NOT_FOUND, WORKSPACE_EXISTS,
NO_WORKSPACE_SELECTED, STORAGE_ERROR, MIGRATION_ERROR,
OPERATION_NOT_FOUND, UNDO_CONFLICT, HISTORY_UNAVAILABLE,
NOT_IMPLEMENTED_YET, INTERNAL_ERROR.
Codes are stable; messages are not a contract.
Messages name the interface the caller is using. A refusal that offers an
override states that interface's own argument: Core's keyword, the CLI's flag, or
the MCP tool argument. The same request therefore reads correctly whether it came
from a library, a shell, or an agent over MCP, and an adapter never prints another
surface's argument. Codes, retryable and details are identical across all
three surfaces.
Safety rules
Confinement. Relative paths resolve inside the workspace root. Absolute paths are accepted only when they land inside it after canonical resolution. Paths containing
..are rejected withPATH_OUTSIDE_WORKSPACE(exit 4). An absolute path that resolves outside is refused withABSOLUTE_PATH_OUTSIDE_WORKSPACE(exit 6), and a symlink whose target leaves the workspace withSYMLINK_ESCAPE_REFUSED(exit 11). A symlink is never a write target (the link itself would be replaced, not its target). Device files, sockets and FIFOs are refused.Credential-shaped targets are refused. Writes to
.env,.env.*,*.pem,*.key,id_rsaand its siblings,*.p12,*.pfx,authorized_keys,.netrc, and anything under.ssh/,.gnupg/or.aws/fail withSENSITIVE_PATH_REFUSED(exit code 10). Override deliberately with--i-accept-secret-write-riskon the CLI,allow_sensitive_write=Truein Core, ori_accept_secret_write_riskon the MCP tool. Each name is long because the mistake is expensive. The error message names only the argument belonging to the interface that received the request.Version-control-ignored targets warn. Writing a path that git ignores still succeeds, but the result carries a warning that the change will not be committed.
No shell. Filekeeper never interpolates paths into a shell command.
Own state is off limits. Paths inside
.filekeeper/are refused, so the tool can never record its own state files in its own history.
Text, binary and size limits
A file is treated as binary when its first 8 KiB contains a NUL byte. Text
operations refuse binary content and undecodable bytes instead of returning
mojibake; --encoding names an encoding explicitly. A UTF-8 byte-order mark is
preserved across rewrites, and line endings are never normalised — the detected
convention is reported, not applied. Line-range edits and patch hunks write
caller content using the file's existing convention, so editing a CRLF file does
not silently convert it to LF.
Reads and writes are bounded (5 MiB and 20 MiB by default), as are search results,
directory entries and recursion depth. Bounded reads report truncated,
truncation_reason and next_start_line instead of quietly returning a prefix.
Adjust the limits in config.toml under [filekeeper] in the home directory.
Python API
from filekeeper import Filekeeper
app = Filekeeper() # or Filekeeper(home="/path/to/home")
app.init()
workspace = app.create_workspace("notes", "/home/me/notes")
service = app.workspace(name="notes") # or root="/path" for a transient workspace
read = service.read_file("todo.md", start_line=1, end_line=20)
service.write_file("todo.md", "# Todo\n", expected_hash=read.content_hash)Mutating methods return MutationResult with operation_id, before_hash,
after_hash, undo_available, summary, warnings and per-path items.
Editing methods add match_stage, match_count, preview_diff and
patch_files.
The same history is available from Python:
record = service.get_operation(operation_id)
recent = service.list_history(path="todo.md", actor="editor", limit=10)
diff = service.diff_operation(operation_id)
service.undo(operation_id, actor="editor")
service.undo_last(actor="editor")Core imports only the Python standard library. packages/filekeeper-mcp/ is a
separate distribution so that installing the CLI never pulls in the MCP SDK; it
ships the STDIO server described above.
Development
uv sync
uv run pytest
uv run ruff check .
uv run mypydocs/decisions.md records the design choices this specification left open.
License
MIT. See LICENSE.
Available Tools
25 toolscontent_searchARead-onlyIdempotent
Search file contents by literal text (default) or a regular expression.
Read-only. Matches carry path, 1-based line number, column and the whole
line. At most 200 matches may be requested; a larger request is refused
with LIMIT_EXCEEDED and a truncated result says so. An invalid regular
expression is INVALID_PATTERN. Binary files are skipped.
| Name | Required | Description | Default |
|---|---|---|---|
| glob | No | ||
| path | Yes | ||
| query | Yes | ||
| regex | No | ||
| max_results | No | ||
| case_sensitive | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With readOnlyHint already declared by annotations, the description goes well beyond: it names the 200-match cap, the LIMIT_EXCEEDED refusal for oversized requests, the truncation marker on truncated results, INVALID_PATTERN for bad regexes, and that binary files are skipped. It also discloses the shape of each match (path, 1-based line, column, whole line) in the absence of an output schema.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the mode selection and read-only status, then error and match-format details. Every sentence carries information; the only mild redundancy is the trailing whitespace/linebreak formatting rather than content.
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?
Covers the critical unknowns for a read-only search tool: match shape (since no output schema exists), result cap and truncation behavior, and error codes. Missing coverage of glob filtering and case-sensitivity default keeps it from being fully complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must carry parameter meaning. It covers query (literal vs regex), the regex toggle, and the max_results ceiling, but leaves glob, path, and case_sensitive (which defaults to true) entirely unexplained — a notable gap for half the parameters.
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 — search file *contents* — which implicitly distinguishes it from the name-based file_search sibling. It doesn't explicitly name file_search or file_read as the alternatives, so differentiation is left partly to inference.
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?
The 'literal text (default) or regular expression' phrasing tells the agent which mode to pick via the regex flag, but there is no guidance on when to use this instead of file_search (name matching) or file_read. Usage is implied by the tool's scope rather than stated.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
directory_createA
Create one directory and return operation_id and undo_available.
Additive: no existing file or directory is replaced. parents controls
whether missing ancestors may be created. dry_run validates and creates
nothing. Otherwise the operation is recorded, and undo removes the
directory only while everything inside it is exactly what the create
produced.
| Name | Required | Description | Default |
|---|---|---|---|
| path | Yes | ||
| dry_run | No | ||
| parents | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description adds substantial behavior beyond the annotations: it says no existing file or directory is replaced, explains dry_run validation, states that the operation is recorded, and gives nuanced undo behavior tied to whether directory contents match what the create produced. The annotations already declare mutation and non-destructive hints, and the description is fully consistent with them.
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 description is short and front-loaded with the action and return values, followed by distinct behavioral constraints. Each sentence adds useful information without repetition.
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 simple three-parameter mutation, it covers return values, additivity, dry-run behavior, parent creation, and undo limits, while annotations cover the safety profile. It stops short of path semantics and error behavior, so it is strong but not fully complete.
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?
The description meaningfully explains two optional parameters: parents controls missing ancestor creation, and dry_run validates without creating. However, schema description coverage is 0%, and the core path parameter's format, requiredness, and behavior when the path already exists are not described, leaving a meaningful gap.
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 states a specific verb and resource: 'Create one directory,' and also names the return values. The scope ('one') and directory resource make it distinguishable from file_create and directory_delete even though those siblings are not named explicitly.
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 gives clear invocation context by explaining that the operation is additive, that parents controls ancestor creation, and that dry_run validates without creating anything. It does not explicitly route the agent to or away from sibling tools such as directory_delete or file_create, so it falls short of a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
directory_deleteADestructive
Delete one directory and return operation_id and undo_available. Destructive.
A non-empty directory requires recursive true and confirm_recursive true;
one without the other is refused before anything is touched. The scope is
exactly the named subtree inside the selected workspace root — this tool
cannot delete outside it, and Filekeeper's own .filekeeper/ state
directory is refused. dry_run lists what would be removed and deletes
nothing. Otherwise the whole tree is recorded as one operation and is
undoable.
| Name | Required | Description | Default |
|---|---|---|---|
| path | Yes | ||
| dry_run | No | ||
| recursive | No | ||
| confirm_recursive | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true, but the description adds substantial context beyond them: scope is confined to the named subtree in the workspace root, the state directory is refused, mutually-dependent guard flags are validated before anything is touched, and the whole tree is recorded as one undoable operation. Those are exactly the behavioral facts an agent needs before mutating.
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 action, the return values and the destructive warning in the first line, then layers guards, scope and undo semantics. Every sentence adds an operational fact; there is no restatement of the title or 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 destructive 4-parameter mutation with no output schema, the description names the return fields, the refusal conditions, the scope boundary and undoability. An agent could call this correctly and safely without reading anything else.
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 0%, so the description must carry the parameters and it largely does: it explains the interplay of recursive and confirm_recursive, and the semantics of dry_run (lists, deletes nothing). Only 'path' is left implicit via the workspace-root scope wording, with no format or relative-vs-absolute guidance.
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+resource ('Delete one directory') and immediately names the return values (operation_id, undo_available) and the destructive nature. A single-directory subtree scope plus the '.filekeeper/ state directory is refused' rule clearly separates it from file_delete and directory_create among the siblings.
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 states the condition for recursion ('a non-empty directory requires recursive true and confirm_recursive true; one without the other is refused') and prescribes dry_run for previewing. It does not name a sibling alternative (file_delete vs directory_delete), so it stops short of full alternative routing.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
directory_listARead-onlyIdempotent
List directory entries under a workspace-relative path.
Read-only. Recursion depth and entries are bounded by configuration; a
truncated listing says so instead of pretending it is complete. The
server refuses max_entries above 1000. Filekeeper's own .filekeeper/
state directory is never listed.
| Name | Required | Description | Default |
|---|---|---|---|
| glob | No | ||
| path | No | . | |
| recursive | No | ||
| max_entries | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, and destructiveHint=false, so the safety profile is covered. The description adds useful behavior beyond annotations: truncation is signaled, recursion and entries are bounded, max_entries above 1000 is refused, and Filekeeper's .filekeeper state directory is hidden.
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 description is short, front-loaded with the primary action, and every sentence carries useful information: read-only status, bounded results, truncation signaling, max_entries cap, and hidden internal state directory.
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 modest four-parameter listing tool with strong annotations and no output schema, the definition covers the important behavioral constraints. It could be stronger by explaining glob and recursive behavior more directly, but it is largely 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 description coverage is 0%, so the description must compensate. It clarifies that path is workspace-relative and that max_entries has a server-enforced cap of 1000, but it leaves glob and recursive semantics largely undocumented beyond a general statement about configured recursion depth.
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 states a clear verb and resource: 'List directory entries under a workspace-relative path.' It is specific enough to distinguish from mutation siblings like directory_create or directory_delete, though it does not explicitly contrast with search-oriented siblings such as file_search or content_search.
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?
Usage is implied by the listing operation and the workspace-relative path context, but there is no explicit 'use this when' guidance or named alternatives. An agent can infer the basic use case, but the description does not say when to prefer directory_list over file_search or other listing mechanisms.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
file_apply_patchADestructive
Apply a unified diff and return operation_id and undo_available. Destructive.
The whole patch is parsed and every hunk is checked against its file
before a byte is written; a failed or ambiguous hunk rejects the patch
with PATCH_FAILED and leaves the pre-patch state intact. A patch is
limited to 1048576 bytes here. A multi-file patch is recorded as one
logical operation and is undoable, but its application is recoverable,
not atomic across files. dry_run validates and reports every file and
hunk without touching the tree. Renaming patches are refused.
| Name | Required | Description | Default |
|---|---|---|---|
| patch | Yes | ||
| dry_run | No | ||
| i_accept_secret_write_risk | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes well beyond the annotations (which already give destructiveHint=true) by disclosing parse-before-write validation, PATCH_FAILED behavior with pre-patch state preserved, a 1048576-byte limit, and the crucial caveat that multi-file application is 'recoverable, not atomic across files'.
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 essential verb and the destructive warning, and nearly every sentence carries distinct information (validation, size cap, atomicity, dry_run, rename refusal).
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?
No output schema exists, but the description still tells the agent what is returned, and it covers failure modes, limits, and undo semantics for a destructive tool.
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 0%, so the description does the heavy lifting: it explains the patch semantics (unified diff, size cap, rename refusal) and fully explains dry_run's effect. But 'i_accept_secret_write_risk' is never mentioned at all, despite being an unusual, surprising required-of-attention flag.
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 opening line names a specific verb and resource ('Apply a unified diff') and states the return values ('operation_id and undo_available'), which functionally distinguishes this from plain-write siblings like file_write or file_replace_text that take content rather than a diff.
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?
Usage is implied rather than spelled out: 'dry_run validates and reports every file and hunk without touching the tree' tells the agent when to use the dry_run mode, and 'Renaming patches are refused' documents a hard boundary.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
file_copyADestructive
Copy one file inside the workspace and return operation_id and undo_available.
An occupied destination is refused unless expected_destination_hash
matches its current content. The copy is not atomic across its two paths,
but it is recorded as one operation, so undo restores both ends. The
destination is subject to the credential-shaped refusal. dry_run writes
nothing. Otherwise the operation is undoable.
| Name | Required | Description | Default |
|---|---|---|---|
| source | Yes | ||
| dry_run | No | ||
| destination | Yes | ||
| expected_destination_hash | No | ||
| i_accept_secret_write_risk | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes well beyond the annotations: discloses non-atomicity across the two paths, that it is recorded as a single undoable operation restoring both ends, the credential-shaped refusal, and that dry_run writes nothing. These are exactly the risk details an agent needs for a destructiveHint=true 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 purpose and return values, followed by tight behavioral clauses that each add information. Mild deduction for the jargon 'credential-shaped refusal', which is dense and not immediately parseable without the schema.
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?
No output schema exists, yet the description names the returns (operation_id, undo_available) and covers atomicity, idempotent-ish destination guarding, and undo semantics. Only gap is the un-named secret-write parameter, which prevents a 5.
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?
With 0% schema description coverage the description must carry the load, and it does explain expected_destination_hash (must match current content) and dry_run. However, source is unstated and i_accept_secret_write_risk is only alluded to obliquely as 'the credential-shaped refusal' rather than named, leaving two of five parameters under-specified.
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?
Opening sentence gives a specific verb and resource ('Copy one file inside the workspace') plus the return values, which lets an agent separate it from file_move/file_write. It stops short of explicitly contrasting with the copy-adjacent siblings, so it lands at 4 rather than 5.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description is explicit about conditional behavior (occupied destination refused unless expected_destination_hash matches; dry_run writes nothing), which implies when to use those flags. But it never states when to prefer file_copy over file_move or explains the i_accept_secret_write_risk escape hatch, so guidance is implied rather than complete.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
file_createADestructive
Create a new text file and return operation_id and undo_available.
Fails with ALREADY_EXISTS while expected_absent is true (the safe
default); set it false to overwrite an existing file, which makes the
call destructive. Writes are atomic. Credential-shaped targets are
refused with SENSITIVE_PATH_REFUSED unless i_accept_secret_write_risk is
true, which records a warning and is itself undoable. dry_run validates
every guard and writes nothing, returning operation_id null. Otherwise
the operation is recorded and undoable.
| Name | Required | Description | Default |
|---|---|---|---|
| path | Yes | ||
| content | Yes | ||
| dry_run | No | ||
| encoding | No | utf-8 | |
| expected_absent | No | ||
| i_accept_secret_write_risk | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes well past the annotations by disclosing atomic writes, exact error codes (ALREADY_EXISTS, SENSITIVE_PATH_REFUSED), the undo model (operation is recorded and undoable, dry_run returns operation_id null), and the warning-recording side effect of the secret-write flag. The description's "makes the call destructive" is consistent with destructiveHint=true, and nothing is contradicted.
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 action and return values, then layers guards in priority order. Dense and mostly waste-free, though the long compound sentences around the secret-write flag could be split for faster scanning.
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 no output schema, the description does the right thing by naming return fields (operation_id, undo_available) and the failure modes. The one real gap is encoding, an entirely undocumented parameter on a tool whose whole job is writing text.
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 0%, so the description carries the full burden, and it only explains three of six parameters (expected_absent, i_accept_secret_write_risk, dry_run). path and content are left to their bare titles, and encoding is never mentioned at all, so compensation is partial.
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 ("Create a new text file") and immediately names what it returns. The expected_absent guard implicitly separates it from the sibling file_write, but the description never names that alternative, so an agent must infer the boundary rather than read it.
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?
Gives explicit conditional guidance: default fails on existing file, set expected_absent=false to overwrite, use dry_run to validate without writing, use i_accept_secret_write_risk only for credential-shaped targets. This is strong when-to-use coverage, but it stops short of routing the agent toward file_write or file_apply_patch for related editing tasks.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
file_deleteADestructive
Delete one file and return operation_id and undo_available. Destructive.
Deletes exactly the named file: no glob, no recursion, no directory
removal, and no widening of the workspace root. expected_hash refuses the
delete when the content changed since it was read (CONTENT_CONFLICT).
dry_run validates and deletes nothing. Otherwise the operation is
recorded, and undo restores the file while nothing else has recreated
that path.
| Name | Required | Description | Default |
|---|---|---|---|
| path | Yes | ||
| dry_run | No | ||
| expected_hash | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructive=true and non-idempotent, so the safety profile is covered; the description goes well beyond by disclosing that the operation is recorded and undoable while nothing else has recreated the path, and by naming the CONTENT_CONFLICT failure mode. That is real operational context an agent could not 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?
Front-loaded correctly with the core action and return values in sentence one, and the remaining sentences each add a distinct constraint. Minor waste: "Destructive." only restates destructiveHint=true, and the final clause about undo is grammatically tangled.
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?
Covers action, scope limits, precondition behavior, dry-run semantics, return fields (operation_id, undo_available), undo limits, and a named error path — more than enough for a 3-parameter destructive tool with no output schema and full annotation coverage.
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 0%, so the description carries the full burden and does: expected_hash is explained as a precondition guard with a named error code, dry_run as validate-only, and path is constrained semantically (exactly one file, no globbing, no root widening). All three parameters acquire meaning not present in the bare 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?
Opens with a specific verb+resource and an explicit scope constraint ("Delete one file"), then immediately bounds it: no glob, no recursion, no directory removal. That cleanly separates it from siblings like directory_delete, file_delete_lines, and file_apply_patch without naming them.
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?
Gives clear when-to-use context for the optional parameters (expected_hash refuses on content change, dry_run validates without deleting) and implicitly excludes directory/multi-file deletion. It stops short of naming an alternative tool to use when the target is a directory, leaving that routing to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
file_delete_linesADestructive
Delete an inclusive 1-based line range and return operation_id and undo_available.
Out-of-range references are refused, never clamped. The file's newline
convention and byte-order mark are preserved. dry_run returns a unified
diff preview and writes nothing. Otherwise the operation is recorded and
undoable.
| Name | Required | Description | Default |
|---|---|---|---|
| path | Yes | ||
| dry_run | No | ||
| end_line | Yes | ||
| start_line | Yes | ||
| expected_hash | No | ||
| expected_content | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond annotations, it discloses that out-of-range references are refused rather than clamped, newline convention and BOM are preserved, dry_run writes nothing and returns a unified diff, and real operations are recorded and undoable. These are valuable behavioral details for a destructive mutation.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact and front-loaded with the core action, followed by safety and mode details. Every sentence contributes useful information without repetition.
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 mutation with no output schema, it covers return values, dry-run behavior, preservation guarantees, and undoability well. It is only incomplete because expected_hash and expected_content are not explained anywhere.
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 0%, so the description must carry parameter meaning. It clarifies start_line/end_line as inclusive 1-based and explains dry_run, but it never mentions path, expected_hash, or expected_content, leaving important parameters undocumented.
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 states a specific verb and resource: delete an inclusive 1-based line range from a file. This clearly distinguishes it from sibling tools like file_delete (whole file), file_replace_lines, and file_insert_lines.
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 explains the dry_run mode and states that real deletion is undoable, which gives implied usage context. However, it does not explicitly say when to choose this tool over siblings such as file_delete or file_replace_lines.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
file_infoARead-onlyIdempotent
Report metadata for one path, including hash, encoding and newline for text.
Read-only. The content_hash is what the guarded mutating tools accept as
expected_hash. Symlink metadata describes the link, not its target. With
a workspace rooted at the filesystem root, the reported path keeps its
leading '/' so it is exactly the absolute path.
| Name | Required | Description | Default |
|---|---|---|---|
| path | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover read-only/idempotent/non-destructive, yet the description adds real behavioral context beyond them: what fields are reported, that symlink metadata describes the link rather than its target, and the leading-'/' path rule under a filesystem-root workspace. These are exactly the non-obvious traits an agent would otherwise get wrong.
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 is front-loaded in the opening sentence, and each following sentence carries a distinct, non-redundant caveat (hash contract, symlink semantics, path form). No filler or repetition of 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?
With no output schema, the description does list the reported fields and grants the edge-case semantics, which is nearly enough for a one-parameter metadata tool. It never sketches the overall shape of the response (e.g., keys for non-text files or missing paths), so a 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 0% for the single 'path' parameter, so the description must compensate; it partly does by explaining path normalization ('the reported path keeps its leading / so it is exactly the absolute path'). It still doesn't clarify whether the input path may be relative or is resolved against the workspace, leaving a gap.
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 gives a specific verb plus resource ('Report metadata for one path') and enumerates the payload (hash, encoding, newline for text), which cleanly separates it from siblings like file_read or directory_list. An agent can tell immediately that this is a stat-style call, not a content read.
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?
States 'Read-only' and links the tool to a concrete workflow: 'The content_hash is what the guarded mutating tools accept as expected_hash', which effectively tells the caller when this tool is needed (before a guarded mutation). It does not, however, name an alternative sibling or state when not to use it, so it stops 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.
file_insert_linesA
Insert text at a defined position and return operation_id and undo_available.
line is a 1-based line number. position is before or after that line, or
end to append at end of file, which takes no line number; there is no
sentinel line number for end of file. Additive: no existing line is
replaced. dry_run returns a unified diff preview and writes nothing.
Otherwise the operation is recorded and undoable.
| Name | Required | Description | Default |
|---|---|---|---|
| line | No | ||
| path | Yes | ||
| content | Yes | ||
| dry_run | No | ||
| position | No | after | |
| expected_hash | No | ||
| expected_content | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes well beyond the annotations: dry_run writes nothing and returns a unified diff preview, whereas a real call is recorded and undoable, and the response includes operation_id and undo_available. This explains the mutation's reversibility and failure-free preview path, which annotations alone (destructiveHint=false, idempotentHint=false) do not convey.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The return contract is front-loaded and every sentence carries operational meaning, including the defensive note about the absent EOF sentinel. Slightly verbose in its line-wrapped phrasing 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?
For a 7-parameter mutation with no output schema, the description adequately covers the return values (operation_id, undo_available) and preview behavior. It falls short on expected_hash/expected_content, so an agent cannot know how to use the optimistic-concurrency guards without guessing.
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?
With 0% schema description coverage, the description carries the full burden, and it documents line (1-based), position (before/after/end), and dry_run semantics well. However, expected_hash and expected_content — the concurrency/consistency guards — are never mentioned, leaving two behaviorally significant parameters completely opaque.
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 text') plus the scope of the operation (at a defined position) and explicitly contrasts it with replacement tools via 'Additive: no existing line is replaced.' An agent can distinguish this from file_replace_lines/file_delete_lines 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?
Explains the line/position mechanics concretely, including the special 'end' case and the warning that no sentinel line number exists for EOF, plus when dry_run applies. It does not explicitly name a sibling alternative ('use file_replace_lines when...'), but the additive-versus-replace distinction effectively routes the agent.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
file_moveADestructive
Move or rename one file inside the workspace and return operation_id and undo_available.
An occupied destination is refused unless overwrite is true, which makes
the call destructive at the destination. The move is recorded as one
operation and undo restores both ends. Credential-shaped destinations are
refused. dry_run writes nothing. Otherwise the operation is undoable.
| Name | Required | Description | Default |
|---|---|---|---|
| source | Yes | ||
| dry_run | No | ||
| overwrite | No | ||
| destination | Yes | ||
| i_accept_secret_write_risk | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description adds substantial context beyond the destructiveHint annotation: overwrite makes the call destructive only at the destination, undo restores both ends, the move is recorded as one operation, credential-shaped destinations are refused, and dry_run writes nothing.
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 description is front-loaded and appropriately short, with the main behavior and constraints stated up front. There is minor redundancy between "undo restores both ends" and "Otherwise the operation is undoable," but it remains efficient.
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 tool with no output schema, the description helpfully states the return fields operation_id and undo_available and covers the main mutation risks. It is not fully complete because the i_accept_secret_write_risk parameter and its interaction with the credential-destination refusal are left unexplained.
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?
With 0% schema description coverage, the description usefully explains overwrite, dry_run, and the source/destination purpose. However, it does not explain i_accept_secret_write_risk at all, and it gives no path-format guidance, so it only partially compensates for the schema gap.
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 states a specific verb and resource: "Move or rename one file inside the workspace." It also names the return values, which makes the tool clearly distinguishable from copy/delete siblings.
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 gives clear usage conditions and exclusions: occupied destinations are refused unless overwrite is true, credential-shaped destinations are refused, and dry_run writes nothing. It does not explicitly name alternatives such as file_copy for copying, so it stops short of the top score.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
file_readARead-onlyIdempotent
Read a text file, optionally a bounded line range.
Line numbers are 1-based and inclusive. Omitting both returns from the
first line. A byte limit smaller than the range truncates honestly:
truncated, truncation_reason and next_start_line say where to resume. A
UTF-8 byte-order mark is preserved and line endings are returned exactly
as stored. Binary content is refused with BINARY_CONTENT_REFUSED unless
an encoding is named. Read-only; no history is recorded. With a
workspace rooted at the filesystem root, the reported path keeps its
leading '/' so it is exactly the absolute path.
| Name | Required | Description | Default |
|---|---|---|---|
| path | Yes | ||
| encoding | No | ||
| end_line | No | ||
| max_bytes | No | ||
| start_line | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The annotations already establish read-only, idempotent, non-destructive, and closed-world behavior. The description adds substantial beyond that: binary content is refused with BINARY_CONTENT_REFUSED unless an encoding is named, truncation fields indicate where to resume, BOMs are preserved, line endings are returned exactly, and no history is recorded.
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 purpose is front-loaded in the first sentence, and the remaining sentences focus on relevant edge cases and return behavior. The description is somewhat dense but every sentence provides useful operational detail, with little waste.
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?
The tool has five parameters, no schema descriptions, no output schema, and annotations that cover safety. The description compensates well by explaining line ranges, encoding, byte truncation, resume fields, BOM handling, line endings, and binary refusal. Minor gaps remain around general output shape and path input semantics, but the description is substantially complete.
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?
With 0% schema description coverage, the description carries the burden of explaining parameter meaning. It covers the 1-based inclusive line range, omitting both line parameters, max_bytes truncation behavior, encoding behavior for binary content, and path reporting semantics. It does not fully specify path input expectations such as relative versus absolute paths.
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 uses a specific verb and resource: "Read a text file, optionally a bounded line range." It is immediately clear what the tool does and that line-range access is optional, but it does not explicitly distinguish itself from siblings such as file_read_many or content_search.
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?
The description gives useful usage context for line ranges, including that omitting both line parameters returns from the first line. However, it does not say when to use this tool instead of alternatives like file_read_many, file_info, or content_search, leaving sibling selection to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
file_read_manyARead-onlyIdempotent
Read several text files in one call (at most 32 paths).
Each entry reports its own path, ok flag, result or error; one missing
file does not hide the others. Line numbers are 1-based and inclusive and
apply to every file. The call itself is read-only. More than 32 paths is
refused with LIMIT_EXCEEDED rather than silently truncated.
| Name | Required | Description | Default |
|---|---|---|---|
| paths | Yes | ||
| end_line | No | ||
| start_line | No | ||
| max_bytes_per_file | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint/idempotent/non-destructive, so the description's added value is the partial-failure contract ('one missing file does not hide the others') and the over-limit behavior ('refused with LIMIT_EXCEEDED rather than silently truncated'). That is meaningful beyond the annotations, though nothing is said about max_bytes_per_file truncation behavior.
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?
Four short sentences, front-loaded with the operation and its hard limit, then failure semantics, then line-number semantics. 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?
Per-entry result shape is described, which is valuable given there is no output schema, and the limit/error contract is covered. The gap is max_bytes_per_file: its units, truncation/error behavior, and interaction with max_bytes limits are unexplained.
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 0%, so the description must compensate; it does so for paths (hard cap of 32) and start_line/end_line (1-based, inclusive, applied to every file). Only max_bytes_per_file is left without any semantic explanation, keeping this short of 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 (read) plus resource (several text files) and explicit batching scope ('in one call, at most 32 paths'). This cleanly distinguishes it from the single-file sibling file_read without the agent needing to inspect 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?
The phrase 'in one call' implies batch efficiency versus repeated file_read calls, but it never explicitly names file_read or states when to choose one over the other. Usage is implied rather than stated.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
file_replace_linesADestructive
Replace an inclusive 1-based line range and return operation_id and undo_available.
Use this for genuinely positional work; file_replace_text is cheaper when
the line numbers are not already known. Out-of-range references are
refused, never clamped. The file's newline convention and byte-order mark
are preserved, and a replacement without a trailing newline does not fuse
lines. dry_run returns a unified diff preview and writes nothing.
Otherwise the operation is recorded and undoable.
| Name | Required | Description | Default |
|---|---|---|---|
| path | Yes | ||
| dry_run | No | ||
| end_line | Yes | ||
| start_line | Yes | ||
| replacement | Yes | ||
| expected_hash | No | ||
| expected_content | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already flag destructive/not-idempotent, and the description adds substantial beyond-schema behavior: out-of-range is refused rather than clamped, newline convention and BOM are preserved, no line fusion without trailing newline, dry_run writes nothing, and successful writes are recorded and undoable. It omits what happens when expected_hash/expected_content preconditions fail, which is the one behavioral gap.
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 action and return values, and each sentence adds a distinct fact. Slightly longer than necessary and the newline-fusion sentence is a touch verbose, but nothing 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 no output schema, the description helpfully names the return contract (operation_id, undo_available, unified diff on dry_run) and the write/undo lifecycle. It is only incomplete around the precondition parameters and their failure behavior.
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 0%, so names alone carry the parameters. The description rescues start_line/end_line (inclusive, 1-based, out-of-range refused) and dry_run (returns a unified diff, writes nothing), but says nothing about expected_hash or expected_content, leaving two concurrency-guard parameters entirely unexplained.
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 and resource — replace an inclusive 1-based line range — and immediately distinguishes itself from the sibling file_replace_text by cost/positional semantics. An agent can tell exactly which file-edit sibling to pick.
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 names the alternative (file_replace_text) and the condition that should redirect the agent there ('when the line numbers are not already known'), plus the dry_run prerequisite path. No inference required for tool selection.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
file_replace_textADestructive
Replace literal text and return operation_id, undo_available and the match stage.
Matching is staged and the result always names the stage: exact first,
then normalised (indentation and trailing whitespace tolerated, the
replacement re-based onto the matched indentation), then a NO_MATCH
refusal carrying the nearest candidate lines. match is required and is
either first or all; there is no default policy. match_count reports the
matches found, expected_match_count refuses a different number, and
expected_content pins the exact text of one region.
| Name | Required | Description | Default |
|---|---|---|---|
| new | Yes | ||
| old | Yes | ||
| path | Yes | ||
| match | Yes | replacement policy: 'first' or 'all' | |
| dry_run | No | ||
| expected_hash | No | ||
| expected_content | No | ||
| expected_match_count | No | ||
| i_accept_secret_write_risk | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already flag destructiveHint=true and idempotentHint=false, and the description adds real value on top: the staged exact-then-normalised matching ladder, the re-basing of replacement onto matched indentation, and the NO_MATCH refusal that returns nearest candidate lines. It omits any mention of the i_accept_secret_write_risk gate, which is a meaningful behavioral precondition an agent should know about before calling.
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 first sentence front-loads purpose and return values, then the staged-matching and guard-parameter details follow in a compact block. No filler sentences and no repetition of what the schema already declares.
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 9-parameter destructive write tool with no output schema, the description covers matching semantics and the return fields well. It falls short on the safety-relevant parameters (dry_run, expected_hash, i_accept_secret_write_risk) that an agent would need in order to invoke this tool responsibly.
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 only 11% across 9 parameters, so the description carries most of the burden. It explains match (required, first/all, no default), match_count, expected_match_count and expected_content, but leaves dry_run, expected_hash and especially i_accept_secret_write_risk entirely undefined even though their names are not self-explanatory in a destructive context.
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 ('Replace literal text') and names the return payload (operation_id, undo_available, match stage). It does not explicitly distinguish itself from the sibling file_replace_lines or file_apply_patch, so an agent must infer that this tool operates on literal strings rather than line numbers or patches.
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 states that match is required with no default policy and enumerates the two policies, which is genuinely useful selection guidance. However, it never says when to choose this over file_replace_lines or file_apply_patch, nor when to prefer dry_run before committing a destructive edit.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
file_searchARead-onlyIdempotent
Find workspace paths matching a glob, under one directory.
Read-only. At most 200 results may be requested; a larger request is
refused with LIMIT_EXCEEDED. A truncated result says so. Literal file
names are faster with directory_list when the directory is known.
| Name | Required | Description | Default |
|---|---|---|---|
| glob | Yes | ||
| path | Yes | ||
| max_results | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare read-only, idempotent, closed-world, so the safety profile is covered; the description earns credit by adding the 200-result cap, the LIMIT_EXCEEDED refusal, and the fact that truncation is signaled in the response. It stops short of describing match semantics (recursion depth, symlink handling) that affect what gets returned.
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?
Four short sentences, front-loaded with the core action and scope, then limits, then the alternative. No filler and nothing repeated from 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?
There is no output schema, and the description adequately signals the return-shape caveat via the truncation note. For a search tool with three parameters the definition is sufficient to call it correctly, with the remaining gap being glob-pattern semantics and result path formatting.
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 0%, so the description must carry the load. It does add meaning for max_results (upper bound of 200, larger requests refused with LIMIT_EXCEEDED) and for path (search is confined under one directory), but glob syntax — whether ** recurses, whether matching is case-sensitive, whether results are absolute or relative — is left undocumented.
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 ("Find workspace paths matching a glob") and immediately bounds the scope ("under one directory"). It also distinguishes itself from the closest sibling by noting that literal file names are faster with directory_list.
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?
Names one explicit alternative (directory_list) with the condition that selects it (directory known, literal name). It does not address the other plausible confusion with content_search (searching by file contents), so the routing guidance is real but incomplete.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
file_writeADestructive
Replace a whole file with new content and return operation_id and undo_available.
The replacement is atomic: a crash leaves the complete previous content.
expected_hash guards against clobbering a file that changed since it was
read; a mismatch is CONTENT_CONFLICT and nothing is written. The file's
encoding and byte-order mark are inherited unless encoding is named.
Credential-shaped targets are refused unless i_accept_secret_write_risk
is true. dry_run validates and writes nothing. Otherwise the operation is
recorded and undoable. Not idempotent: each successful call adds a
history record.
| Name | Required | Description | Default |
|---|---|---|---|
| path | Yes | ||
| content | Yes | ||
| dry_run | No | ||
| encoding | No | ||
| expected_hash | No | ||
| i_accept_secret_write_risk | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description adds substantial behavioral context beyond annotations: atomic replacement, CONTENT_CONFLICT behavior on hash mismatch, encoding/BOM inheritance, credential-shaped target refusal, dry-run semantics, undoability, and non-idempotence with history records. It is fully consistent with destructiveHint=true and idempotentHint=false.
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 description is front-loaded with the core action, then layers in atomicity, conflict handling, encoding, secret refusal, dry-run, undo, and idempotence. Each sentence adds useful operational detail without repetition or fluff.
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 complex destructive write operation with no output schema, the description is substantially complete: it describes the return values (operation_id and undo_available), safety behavior, and conflict handling. The main remaining gap is lack of explicit sibling routing and path-creation semantics.
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?
With 0% schema description coverage, the description carries the burden and explains the non-obvious parameters: expected_hash, encoding, dry_run, and i_accept_secret_write_risk. It does not add details for path or content, such as whether the target must already exist or whether parent directories are created, but the main behavioral parameters are well covered.
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 states a specific verb and resource: 'Replace a whole file with new content.' The word 'whole' distinguishes it from partial-edit siblings such as file_replace_text and file_apply_patch, though it does not explicitly name those alternatives.
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 explains key operating conditions, including expected_hash for conflict avoidance, dry_run validation, and secret-target refusal. However, it does not explicitly say when to use file_write instead of file_create, file_replace_text, or file_apply_patch, so the agent must infer the boundary from the phrase 'whole file.'
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
history_diffARead-onlyIdempotent
Show the recorded before/after unified diff for one operation.
Read-only. Returns one entry per affected path with a textual unified
diff, or is_binary true for content that has no textual diff. Never
returns whole file bodies.
| Name | Required | Description | Default |
|---|---|---|---|
| operation_id | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly/idempotent/non-destructive, and the description adds real value on top: one entry per affected path, a textual unified diff, an is_binary flag for non-textual content, and the guarantee that whole file bodies are never returned. Only error behavior for an unknown operation_id is unstated.
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 first sentence followed by return-shape details, with zero filler. The second paragraph is somewhat terse and line-broken, but every clause carries 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?
For a single-parameter read-only tool this is nearly complete: the return shape, per-path granularity, binary handling, and body-exclusion guarantee are all stated. The only missing piece is how to obtain or validate the operation_id.
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 0% for the single operation_id parameter, and the description only implies it by saying 'for one operation'. It does not say where the identifier comes from (e.g., history_list results) or what format it takes, so the gap is only partly compensated.
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 and resource ('Show the recorded before/after unified diff for one operation'), which is clearly distinct from history_list/history_get metadata tools. It does not explicitly name those siblings, but the returned artifact (diff) is 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?
Usage is implied rather than stated: the agent must infer it is used after identifying an operation via history_list, and no guidance is given about when to prefer this over history_get or when a diff is unnecessary. There are no explicit exclusions or alternatives.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
history_getARead-onlyIdempotent
Show one recorded operation: status, actor, paths, before/after hashes and modes.
Read-only. Unknown identifiers are OPERATION_NOT_FOUND. No file content is
returned; use history_diff for a before/after diff.
| Name | Required | Description | Default |
|---|---|---|---|
| operation_id | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint/idempotent/non-destructive, so the bar is lower, yet the description adds genuinely new behavior: the OPERATION_NOT_FOUND failure mode for unknown identifiers and the explicit boundary that no file content is returned. It does not address ordering, size of result, or permissions, which keeps it from a 5.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three short sentences, front-loaded with what is returned, followed by safety/error and the sibling redirect. No filler and nothing repeated verbatim from the schema.
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 no output schema, the description compensates by enumerating the returned fields, and annotations cover the safety profile. The remaining gap is that it never says where operation_id values come from (history_list), which an agent needs to actually reach a successful 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 0%, so the description must carry the burden for the single parameter and it largely does: operation_id is framed as identifying one recorded operation, and the 'Unknown identifiers are OPERATION_NOT_FOUND' clause tells the agent what an invalid value produces.
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 ('Show one recorded operation') and immediately enumerates what is returned: status, actor, paths, before/after hashes and modes. It explicitly contrasts itself with the sibling history_diff, so an agent can distinguish the two 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?
Gives clear retrieval context and names the alternative: 'use history_diff for a before/after diff.' It does not, however, explain how an operation_id is obtained (e.g., via history_list) or state when this is a poor choice beyond the diff case.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
history_listARead-onlyIdempotent
List recorded operations in the selected workspace, newest first.
Read-only. path narrows to operations touching that workspace-relative
path; actor and task_id are filters, not authority, and never change what
a mutation records. limit is capped at 200. Returns operation ids usable
with history_get, history_diff and undo_operation. Paths are rendered
when read: a workspace rooted at the filesystem root reports target and
item paths with their leading '/' so they are absolute.
| Name | Required | Description | Default |
|---|---|---|---|
| path | No | ||
| actor | No | ||
| limit | No | ||
| task_id | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover read-only/idempotent safety, and the description goes well beyond them: newest-first ordering, a hard limit cap of 200, and the non-obvious path-rendering quirk where a workspace rooted at the filesystem root reports absolute paths with leading '/'. It also clarifies that actor/task_id do not change what a mutation records, heading off a likely misinterpretation.
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 and ordering are front-loaded in the first sentence, and the filter/limit facts follow logically. The standalone "Read-only." sentence is redundant with readOnlyHint=true, and the path-rendering aside is dense enough to slow parsing, but nothing is 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?
With 0% schema coverage, no output schema, and four parameters, the description does the necessary work: it explains the return (operation ids usable downstream) and covers each parameter's role. It stops short of complete because actor/task_id semantics stay thin and the limit-overflow behavior is unstated.
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 0%, so the description must carry all four parameters, and it largely does: path's narrowing semantics and rendering, actor/task_id as filters with no authority, and limit's 200 cap. Gaps remain — it doesn't define what 'actor' identifies (who performed the operation vs. who is viewing) and 'capped at 200' is ambiguous about whether larger values error or clamp.
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 recorded operations") plus the scope ("in the selected workspace") and ordering ("newest first"). It also names the sibling tools that consume the returned ids (history_get, history_diff, undo_operation), so an agent can place it in the family without opening another schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It establishes filtering intent — path narrows to operations touching that path, while actor and task_id are filters, not authority — and points to history_get/history_diff/undo_operation as follow-ups. It never states an explicit exclusion (e.g. when to prefer history_get directly or whether single-operation lookup requires this call first), so it falls short of a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
undo_lastADestructive
Undo the most recent undoable operation in the selected workspace. Destructive.
Same conflict rules as undo_operation: any path changed after the
operation refuses the whole undo with UNDO_CONFLICT and modifies nothing.
history_skipped entries in the result were above the history size cap and
cannot be restored (HISTORY_UNAVAILABLE). The undo is itself recorded.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true, readOnlyHint=false and idempotentHint=false, so 'Destructive.' adds little. However the description adds substantial non-redundant behavior: an all-or-nothing conflict rule (any later path change aborts with UNDO_CONFLICT and modifies nothing), non-restorable history_skipped entries (HISTORY_UNAVAILABLE), and the fact that the undo is itself recorded in history.
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 core action in the first clause and follows with the failure semantics that matter. Only waste is the one-word 'Destructive.' sentence, which merely restates destructiveHint=true.
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 no parameters and no output schema, the description carries the burden of explaining outcomes, and it does explain the abort code, the partial-restore limitation, and side effects on history. It is slightly incomplete on what a successful result contains beyond history_skipped (e.g. a list of restored paths).
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?
The tool takes zero parameters, so the baseline is 4. The description does not need to explain any inputs, and its added detail about result codes (UNDO_CONFLICT, HISTORY_UNAVAILABLE) concerns outcomes rather than parameters.
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 ('Undo the most recent undoable operation') and scopes it to 'the selected workspace'. It also names its sibling operation (undo_operation) for the shared conflict semantics, so an agent can distinguish the two 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?
Usage is implied rather than stated: 'most recent undoable operation' suggests use when you want a blind rollback, but it never says 'use undo_operation instead when you have a specific operation id' or what happens if no undoable operation exists. It also does not explain how the 'selected workspace' is established.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
undo_operationADestructive
Undo one recorded operation and return the new operation_id and undo_available.
Before writing, every affected path is compared with the operation's
recorded before and after state. A path that matches neither was changed
afterwards: the whole undo is refused with UNDO_CONFLICT and nothing is
modified. A recorded move, copy or multi-file patch is undone as one
operation. Undoing a create removes the file only while it still matches
what was created. The undo is itself recorded; a refusal is recorded as an
undo_refused row carrying the conflict code and the blocking paths, and
that row is never offered as undoable.
| Name | Required | Description | Default |
|---|---|---|---|
| operation_id | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Substantially exceeds the annotations (destructive=true, idempotent=false) by describing the before/after verification pass, all-or-nothing refusal with UNDO_CONFLICT and zero modification, atomic handling of moves/copies/multi-file patches, the create-undo precondition, and that refusals are logged as undo_refused rows that are never offered as undoable. This is exactly the kind of consequence-level detail an agent needs before invoking a destructive tool.
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 return values, then the failure modes. Dense but every sentence adds behavioral information; slightly verbose in the multi-file/move-copy enumeration but not padded.
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?
No output schema exists, yet the description names the returned fields (operation_id, undo_available) and explains conflict/refusal outcomes thoroughly. The remaining hole is provenance of the operation_id, which an agent must guess.
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?
With one parameter and 0% schema description coverage, the description carries the burden; it only conveys indirectly that operation_id identifies 'one recorded operation'. It never states the id format, source (history_list?), or whether cross-workspace ids are valid, so the gap is only partially closed.
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+resource ('Undo one recorded operation') plus the return values, which is unambiguous about what the tool does. It implicitly separates itself from undo_last by emphasizing 'one recorded operation' (id-driven) but never names that sibling, so it falls short of full differentiation.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is only implied: taking an operation_id suggests the caller already has a recorded operation from history, but the description never says where to get that id or when to prefer this over undo_last. No exclusions or prerequisites are stated.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
workspace_infoARead-onlyIdempotent
Describe the selected workspace, or one registered workspace by name.
Read-only. Reports the workspace name, identifier, registered root and
whether the selection is a transient --root rather than a registration.
It also reports the server's own package ``version``, so a caller can
record which build it measured without running the binary.
It does not create, select or modify a workspace.
| Name | Required | Description | Default |
|---|---|---|---|
| workspace | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, idempotentHint=true and destructiveHint=false, so "Read-only" in the description is largely redundant. What it does add is the payload shape (transient --root vs registered root, plus the server package version for build provenance), which is genuinely useful context beyond the annotations. It does not say how an unknown workspace name is handled.
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 scope in the first sentence, followed by return contents and an exclusion. The "Read-only" line duplicates the annotation, and the line breaks inflate it slightly, but no sentence is 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 one-parameter, non-mutating tool with no output schema, the description covers purpose, return fields, and scope exclusions. The only real omission is error behavior for an invalid workspace name, which is minor given the simplicity.
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 0% for the single `workspace` parameter, so the description must carry the meaning. "One registered workspace by name" establishes that the value is a name of a registered workspace and that the null default means the current selection. It omits the failure behavior for an unregistered 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?
States a specific verb+resource ("Describe the selected workspace, or one registered workspace by name") and enumerates exactly what is reported: name, identifier, registered root, transient --root status, and server version. This clearly separates it from the sibling workspace_list, which enumerates workspaces rather than describing one.
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?
The two calling modes are implied precisely: omit the argument to describe the current selection, supply a name to describe a specific registration. It also adds an exclusion ("does not create, select or modify a workspace"), which steers an agent away from treating this as a selection tool. It stops short of naming workspace_list as the alternative for enumeration.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
workspace_listARead-onlyIdempotent
List the workspaces registered in the server's home directory.
Read-only. The configured default is named separately. Registration is administration done elsewhere; this tool never registers or removes one.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare read-only, idempotent, non-destructive, and non-open-world behavior. The description adds useful context beyond that: workspaces come from the server's home directory, the default is named separately, and this tool never registers or removes workspaces. It does not describe return shape, but the safety profile is well covered.
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 description is short and front-loaded, starting with the core action and then adding relevant boundaries. Every sentence contributes useful scope or exclusion information without 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?
For a simple zero-parameter read-only list tool with rich annotations, the description is nearly complete: it states the data source and excludes registration/removal. The main gap is that it does not describe the return value shape, which matters somewhat because there is no output schema.
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?
There are no parameters, so there are no parameter semantics to explain. The baseline for a zero-parameter tool is 4.
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 states a specific verb and resource: list workspaces registered in the server's home directory. It clarifies that the configured default is named separately and that registration/removal is done elsewhere, though it does not explicitly distinguish this from the sibling workspace_info tool.
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?
Usage is implied by the scope: use this to list registered workspaces, not to register or remove them. However, the description does not explicitly say when to choose this over workspace_info or directory_list, leaving routing 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.
25 tool updates
v0.1.8- First observed
content_search - First observed
directory_create - First observed
directory_delete - First observed
directory_list - First observed
file_apply_patch - First observed
file_copy - First observed
file_create - First observed
file_delete - First observed
file_delete_lines - First observed
file_info - First observed
file_insert_lines - First observed
file_move - First observed
file_read - First observed
file_read_many - First observed
file_replace_lines - First observed
file_replace_text - First observed
file_search - First observed
file_write - First observed
history_diff - First observed
history_get - First observed
history_list - First observed
undo_last - First observed
undo_operation - First observed
workspace_info - First observed
workspace_list
TDQS
Scored across 25 tools
Tools are largely distinct by resource and action, and descriptions clarify overlapping edit operations such as create vs write and text replacement vs line replacement. A few clusters, especially the multiple granular edit tools and undo_operation vs undo_last, require reading descriptions, but there are no true duplicates.
Most names follow a predictable resource_action pattern, e.g. file_read, directory_delete, history_diff. Exceptions such as undo_operation, undo_last, and workspace_info are still readable but break the dominant pattern slightly.
At 25 tools this is heavy for a file-management server, even though many tools are purposeful and distinct. The granular read/edit/history surface sits at the upper boundary and could likely be consolidated somewhat.
The surface covers workspace introspection, file and directory reads, search, metadata, file and directory lifecycle operations, line and text editing, patch application, history inspection, and undo with conflict handling. No obvious lifecycle or recovery gaps appear for the stated filekeeper domain.
Maintenance
Related MCP Connectors
A real-time, multiplayer filesystem for agents and humans: shared files, live edits, history.
Securely search and manage workspace context files for AI agents and teams.
Execution control plane for agents: capabilities, durable jobs, budgets, receipts, and BYOK.
Scoped agent execution. Server-side credentials, policy, budgets and verifiable receipts.
Related MCP Servers
- AlicenseNot gradedqualityAmaintenanceEnables AI agents to perform workspace file operations (read/write/recover) with transaction-safe guarantees, durable recovery, and explicit human approval via a separate Broker.MIT
- AlicenseNot gradedqualityAmaintenanceEnables coding agents to compile change plans into canonical, content-addressed manifests, run whole-set checks, and apply writes through a hash-gated two-phase commit with rollback and optional attestation.MIT
- AlicenseNot gradedqualityBmaintenanceEnables LLM clients to search, read, and patch a trusted source repository with rollback-safe edits, Git operations, and allowlisted validation over stdio or OAuth-protected HTTP. Keeps secrets and arbitrary shell access out of reach while enforcing bounded batched I/O and operator-controlled workspace trust.MIT
- AlicenseNot gradedqualityCmaintenanceEnables MCP-capable coding agents to perform batched, token-efficient file and search operations with tolerant, automatically verified edits and diffs. It supports sandboxed workspace access, optional command execution, caching, and post-edit syntax/import checks.MIT