Skip to main content
Glama
mariusei

Scantool - File Scanner MCP

by mariusei

Scantool: give your coding agent a map of the codebase

PyPI version License: MIT

Claude Code, Cursor and VS Code agents find a function by reading whole files. Scantool gives them the structure instead: every class, function, caller and heading with its line numbers, in one call, so the agent reads only what it needs. It works on code and on documents, and it needs no index, no API keys and no setup beyond one command.

Under the hood: a tree-sitter parser for 20+ languages, exposed as an MCP server and as sct, a shell command the agent runs itself.

Measured on real agent episodes (2026-06-10 and 2026-06-11, Haiku subagents, same tasks in both arms):

"Where is the cache invalidated?"    scantool   378 tokens / 1 call
                                     grep      9,370 tokens / 4 calls    -> 25x less

pytest skipif-caching bug            scantool   solved in 3 calls
                                     grep       gave up after 13,450 tokens

Read tokens per episode, same         with focus     13,523
fact coverage in both arms            without        54,337               -> 75% less

Across 22 episodes the scantool agents answered with 88% fact coverage against 73% for a grep-only agent: better-anchored answers, fewer wrong files. Grep still wins plain literal lookups and top-level overviews, by 1.4x and 1.6x. Both axes are measured and the losses are reported in experiments/benchmark/.

What you use it for

Each of these is one command in the agent's shell, or the matching MCP tool.

Where is X handled in this codebase?

sct search . "cache invalidat"

Every hit arrives with the function or class it sits in, the line range, and leads to the definitions it calls. The agent does not open the file to find out what the match belongs to. This is the case measured at 378 tokens against 9,370 for grep.

Get oriented in an unfamiliar repo before changing it

sct .

Language mix, entry points, the most-called functions and the central files, in 3 to 5k tokens. What it printed on scantool's own source, trimmed:

━━━ ENTRY POINTS ━━━
  server.py:main() @1658
  cli.py:main() @562
  languages/__init__.py:__all__ (13 items)

━━━ core: CORE FILES (by centrality; used by = files that import it, resolved statically) ━━━
  languages/models.py: imports 0, used by 33 files
     class StructureNode [called by 178]

Read one function without guessing line ranges

sct focus src/scantool/capabilities.py capability_of_tool
src/scantool/capabilities.py::capability_of_tool (270-274)
capabilities.py (1-333)
- module docstring @1 # FILE: capabilities.py
- import statements @30
- Capability @34
   @dataclass(frozen=True)
- CAPABILITIES = (Capability(command='', usage=('sct <dir> [--…',), short='o… @45
- capability (command: str) -> Capability @263
- capability_of_tool (tool: str) -> Capability @270
   270 | def capability_of_tool(tool: str) -> Capability:
   271 |     for entry in CAPABILITIES:

The node comes verbatim with line numbers, the rest of the file as a one-level outline, so the agent sees where it sits. In the M2c episodes this cut read tokens by 75% at unchanged fact coverage.

What did this branch change, structurally?

sct diff main

Per file: + added, ~ changed (signature, value or body), = renamed (paired by identical body), - removed, each with the caller count among the changed functions. Three functions with the same signature change fold into one row. It replaces reading a full git diff to answer "what changed".

Who calls this function?

sct callers condense_excerpt --dir src/scantool

Actual call sites with their enclosing function and path:line, definitions first. Mentions in comments, docstrings and strings are not calls and never appear.

sct callers src/scantool/code_map.py

Given a file, the files that import it, each with the import line: the number the preview prints as used by N files, computed from the same statically resolved import graph.

Will these branches collide when merged?

sct overlap main feat/a feat/b

Structures two or more branches touch, names two branches introduced independently, and a merge-order hint. Each branch is compared at its own merge-base.

Did the public API change?

sct surface src/scantool --against v0.25.0

Every exported name with its signature and where it is defined after re-exports, and the diff of that surface between two refs.

Is a changed function out of step with its siblings?

sct divergence <dir>, and the same section inside sct diff --review, lists functions that break a call pattern their peers follow: callers of X also call Y, this one does not. It is a place to look, never a verdict. On a consistent codebase it prints nothing.

Find a section in a long Markdown, SQL or config file

sct focus docs/notes.md "Quick Start"
sct scan schema.sql --depth quick

Headings, tables, views, keys and cells are nodes with line ranges, addressed the same way as functions. Code-only tools stop at the source files; a project's documentation, schema and configuration are the same kind of structure here.

Make Claude Code use fewer tokens on a large codebase

Install once, and the agent gets search_structures, scan_file with focus= and scan_diff as MCP tools, plus sct in its shell. The tool descriptions tell it when to reach for each, and the numbers at the top of this page are what that saved in measured episodes.

When grep is the better tool

Literal lookups of a known string, and overviews whose answer sits in the top-level files. In the M2 tasks grep won those by 1.4x and 1.6x. Scantool wins when the question is about a concept or a structure, because the answer needs the enclosing context and grep has to open files to get it.

Related MCP server: MCP Codebase Symbols Server

Install

Scantool runs through uv. Install uv first; without it the server fails silently to start.

curl -LsSf https://astral.sh/uv/install.sh | sh    # macOS, Linux, WSL

Then, in Claude Code:

claude mcp add --scope user scantool -- uvx scantool

Restart Claude Code. Every other client takes the same entry in its own config file:

{
  "mcpServers": {
    "scantool": {
      "command": "uvx",
      "args": ["scantool"]
    }
  }
}

Client

Config file

Claude Desktop (macOS)

~/Library/Application Support/Claude/claude_desktop_config.json

Cursor

~/.cursor/mcp.json, or .cursor/mcp.json per project

Windsurf

~/.codeium/windsurf/mcp_config.json

VS Code (Copilot agent mode)

.vscode/mcp.json, with the top-level key servers instead of mcpServers

Cline

MCP Servers panel, or ~/.cline/mcp.json for the CLI

Your team

.mcp.json in the project root; Claude Code asks each member once

Windows, install from source, the HTTP transport and troubleshooting are in docs/install.md.

Every install has one side effect: when the server starts it also writes sct into uv's tool bin directory, so the agent has the same reader in its shell. SCANTOOL_NO_CLI=1 opts out. Details in docs/sct.md.

sct in the shell

Agents read most code through their shell, not through MCP tools. sct is the same reader as a shell command, under the same interpreter as the server:

sct <dir> [--part ID] [--lines N]
sct scan     <path>... [--ref REF] [--budget N] [--depth quick|normal|deep] [--lines N]
sct scan     - [...]                     paths from stdin, one per line
sct scan     - --as <path> [...]         stdin content scanned as <path>
sct focus    <path> <name|heading> [--ref REF] [--body] [--lines N] [--json]
sct focus    <path>::<name>[@REF]        the address form, one argument
sct focus    - --as <path> <name>        stdin content, one node
sct search   <dir> <pattern> [--ref REF] [--names] [--type TYPE] [--limit N] [--offset N] [--lines N]
sct search   <dir> <pattern> --names --decorator RE   one row per structure, decorators on the row
sct diff     <refA> [<refB>] [--repo DIR] [--path PATH] [--no-merge-base] [--review]
sct surface  <package-dir> [--ref REF] [--against REF] [--part ID]
sct overlap  <base> <branch>... [--repo DIR] [--path P] [--kind K] [--part ID]
sct callers  <name|file> [--dir DIR] [--ref REF]
sct resolve  <path:line | path::name> --from REF --to REF [--repo DIR]
sct divergence <dir> [--max-findings N]
sct history  <path::name | path:line> [--ref REF] [--repo DIR]
sct <command> --help                             the full help; --json on every command but <dir> and divergence, --ascii anywhere

Output is valid input. A focus answer opens with the node's address, path::Qualified.name (a-b), and that address is one argument that reads it again. --ref reads at any git ref without a checkout. When a budget cut something, one trailer names the call that recovers the most. Each command's full description is in sct <command> --help and in docs/sct.md.

How it works

Scantool parses files on demand with tree-sitter and keeps no index. A parsed file is cached by its git blob id, so the same bytes at a ref, on stdin or in the next process do not parse twice.

Functions are shown as condensed skeletons: control flow, calls and returns kept, trivial statements folded to . The most salient functions get full depth, the rest a two-level outline. Both the tiers and the defaults are the measured optimum for fact coverage per token (experiments/condensation/, experiments/entropy_metrics/); parameters are escape hatches, not style choices.

Nothing is dropped silently. Every answer opens with a coverage line that counts files seen, structures shown, and what was excluded and why:

<63 files seen, 1501 structures shown, 3 excluded (__pycache__/), 1 unsupported (.typed)>

The output format is the API. Agents consume it directly, so format drift is behaviour drift in the consumer. The default format is frozen by golden tests (tests/golden/), in tree and JSON form, and a change to it is a deliberate snapshot update. The contract in full is in CONTRIBUTING.md.

Compared with

The three largest code-exploration MCP servers take different routes, and each route has a cost scantool does not pay. Checked against their own documentation on 2026-06-11.

Reads the code by

Runs an index or server

API keys

Edits code

Scantool

Parsing on demand, structure with line numbers

No

No

No

Repomix

Packing the whole repo into one file the agent reads in ranges

No (a pack step)

No

No

Serena

Language servers, symbol by symbol

A language server per language

No

Yes

claude-context

Embedding index with hybrid search

A vector database

Yes

No

None of the three extract headings, tables or keys from documents as addressable structure.

The trade-off in this category is measured. An index-based tree-sitter MCP reported 10x fewer tokens and 2.1x fewer tool calls at 83% answer quality against 92% for a raw file-exploration agent, across 31 repositories (arXiv 2603.27277, March 2026, self-reported). Scantool's own numbers above show where it wins and where grep does, on the same footing. Serena's editing is a different job and scantool does not attempt it.

Supported languages

Extension

Language

Extracted elements

.py, .pyw

Python

classes, methods, functions, imports, decorators, docstrings, constants

.js, .jsx, .mjs, .cjs

JavaScript

classes, methods, functions, imports, JSDoc comments, constants

.ts, .tsx, .mts, .cts

TypeScript

classes, methods, functions, imports, type annotations, JSDoc, constants

.rs

Rust

structs, enums, traits, impl blocks, functions, use statements, constants

.go

Go

types, structs, interfaces, functions, methods, imports, constants

.c, .h

C

functions, structs, enums, includes, constants

.cpp, .hpp, .cc, .hh

C++

classes, functions, namespaces, templates, includes, constants

.java

Java

classes, methods, interfaces, enums, annotations, imports

.php

PHP

classes, methods, functions, traits, interfaces, namespaces, constants

.cs

C#

classes, methods, properties, structs, enums, namespaces

.rb

Ruby

modules, classes, methods, singleton methods, constants

.zig

Zig

functions, structs, enums, unions, tests, constants

.swift

Swift

classes, structs, enums, protocols, functions, extensions, constants

.sql

SQL

tables, views, functions, procedures, indexes, columns

.html

HTML

document structure, elements, attributes

.css

CSS

selectors, properties, media queries

.scss

SCSS

selectors, mixins, variables, nesting

.yaml, .yml

YAML

mappings, sequences, scalars, anchors/aliases, multi-document streams

.md

Markdown

headings (h1-h6), code blocks with hierarchy

.ipynb

Jupyter

cells, and inside them the Python and Markdown structure

.txt

Plain Text

sections, paragraphs

.json

JSON

object keys (nested fully), arrays with item counts, scalar values

.toml

TOML

tables, array tables, nested keys, inline tables, arrays with item counts

.png, .jpg, .gif, .webp

Images

format, dimensions, colors, content type

Broken files fall back to regex extraction, so a file that no longer parses still yields its structure. Adding a language is one file; see CONTRIBUTING.md.

MCP tools

The same capabilities as sct, for clients without a shell. Each tool's description tells the agent when to use it. Parameters, defaults and example output are in docs/tools.md.

Tool

What it answers

preview_directory

Orientation: entry points, hot functions, central files, call map

scan_directory

The file tree with one-line gists per file, churn and health labels

scan_file

One file's skeleton; focus= reads one node verbatim; budget= caps the size

scan_file_content

The same reader on content given directly: a git blob, an API response, stdin

search_structures

Text or name search with the enclosing structure and leads to definitions

list_directories

Folders only

scan_diff

Structural diff between refs, or a ref and the working tree; review=True adds divergence

surface

A package's public names, where each is defined, and the diff against a ref

overlap

Structures several branches touch, and a merge order

callers

Actual call sites of a name

resolve

A path:line or path::name carried from one ref to another

find_divergence

Functions breaking a call pattern their siblings follow

history

Commits that changed one structure

Known limitations

Claude Desktop caps an MCP tool response at 25,000 tokens; Claude Code's cap is set with MAX_MCP_OUTPUT_TOKENS. budget=, depth= and pattern= keep answers under it, and the coverage line says what a cap left out.

Subagents in Claude Code that lack MCP tools still have the shell, and sct is in it. If you want the MCP tool specifically, say so: "use scantool to scan the codebase".

Peer divergence and the connectivity notes are hints from corpus-wide statistics, not verified defects. They tell the agent where to read.

More

MIT License, see LICENSE. Built on FastMCP, tree-sitter and uv.

Available Tools

13 tools
callersCallersA

Actual call sites of a function or method across a directory, never a mention in prose, a comment, a docstring or a string literal; each with its enclosing function and path:line, the definition(s) first. A qualified name (Class.method) narrows the definitions; which definition a site binds to is not resolved, and the answer says so. Given a file instead of a name, the files that import it with the import line, from the same statically resolved import graph as the preview's used by. In your shell: sct callers <name> or sct callers <name> --dir <dir> (if sct is not on PATH, "/app/.venv/bin/python" -m scantool.cli replaces sct).

ParametersJSON Schema
NameRequiredDescriptionDefault
refNo
nameYes
directoryNo.
output_formatNotree

TDQS

A4.3/5.0
Behavior5/5

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

With no annotations, the description carries the full burden and meets it: it discloses the false-positive exclusions, the unresolved definition-binding limitation and that the answer explicitly says so, the different behavior for file inputs, and reliance on the same statically resolved import graph as `used by`.

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

Conciseness4/5

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

The core semantics are front-loaded and every clause adds information, including the shell invocation and PATH fallback. It is long and somewhat dense, but it is not padded.

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

Completeness4/5

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

Despite having no output schema and no annotations, the description conveys the substance of results: definition(s) first, enclosing function, path:line, and the unresolved-binding caveat. The main gap is the undocumented optional parameters `ref` and `output_format`.

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

Parameters3/5

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

The description adds meaning for `name` (function/method or file) and `directory` via `--dir`, which is valuable given zero schema description coverage. However, it never explains `ref` or `output_format`, so an agent cannot know what `ref` refers to or which output formats are valid.

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

Purpose5/5

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

The description names the specific operation: producing actual call sites of a function or method across a directory. It sharply excludes false matches like prose, comments, docstrings, and string literals, and also explains the file-input mode for finding importers.

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

Usage Guidelines4/5

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

The description gives clear usage context: a qualified name narrows definitions, a file input switches the tool to importer discovery, and `--dir` controls the directory scope. It does not explicitly name when-not-to-use sibling tools, but the invocation guidance is concrete and actionable.

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

find_divergenceFind DivergenceA

Peer divergence across a directory: functions that break a call pattern their siblings follow (peers calling X also call Y, this one does not). A review hint, not a verified bug list; silent on a consistent codebase, and that silence is the answer. In your shell: sct --help (if sct is not on PATH, "/app/.venv/bin/python" -m scantool.cli replaces sct).

ParametersJSON Schema
NameRequiredDescriptionDefault
directoryYesRoot directory to audit
max_findingsNoCap on the number of findings shown (default: 20)
respect_gitignoreNoRespect .gitignore patterns (default: True)

TDQS

A3.6/5.0
Behavior4/5

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

With no annotations, the description carries the full burden and does a good job: it discloses that results are review hints, not verified bugs, and explains the meaning of a silent result. It does not mention side effects, permissions, or failure behavior, but the read-only audit nature is strongly implied.

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

Conciseness4/5

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

The description is compact and front-loads the core concept before the caveat and shell usage. The shell command sentence is arguably extra but still useful and does not bloat the description significantly.

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

Completeness3/5

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

The tool's purpose, caveats, and silent-result behavior are covered, but there is no output schema and the description does not explain the structure of the findings. It says 'findings' are capped, but an agent would still wonder what a finding includes or how it is formatted.

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

Parameters3/5

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

All three parameters are fully described in the input schema (100% coverage), so the description does not need to add parameter-level details. The shell command in the description is useful context but does not enhance parameter understanding.

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

Purpose4/5

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

The description clearly defines the tool's purpose with a concrete example of peer divergence ('peers calling X also call Y, this one does not') and immediately qualifies it as a review hint. It does not explicitly differentiate itself from sibling tools like scan_directory or callers, so it misses the top score.

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

Usage Guidelines3/5

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

The description implies this is a heuristic review tool rather than a definitive bug detector, and notes that silence on a consistent codebase is meaningful. However, it does not explicitly say when to choose this over sibling tools or provide when-not-to-use guidance.

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

historyHistoryA

One structure followed backwards through the commits that touched its file: a signature or body change, a rename (paired by identical body, the earlier name followed), the commit that introduced it; a file move is followed. Commits that touched the file but not the structure are counted, not listed. What git log -L gives for a line range, keyed on the structure. In your shell: sct history <path::name> or sct history <path:line> --ref REF (if sct is not on PATH, "/app/.venv/bin/python" -m scantool.cli replaces sct).

ParametersJSON Schema
NameRequiredDescriptionDefault
refNo
repoNo
locationYes
output_formatNotree

TDQS

A3.5/5.0
Behavior4/5

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

With no annotations, the description carries the full burden, and it reveals important behavior: rename detection by identical body, following file moves, counting but not listing unrelated commits, and identifying the introducing commit. This is strong, though output details remain only loosely indicated via the git log -L comparison.

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

Conciseness3/5

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

Every sentence carries substantive information and there is no filler. However, the opening sentence is convoluted and passive, burying the basic 'what this tool does' under tracking details before a cleaner analogy appears.

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

Completeness3/5

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

The description gives rich behavioral rules and concrete invocation examples, but there is no output schema and the return format is only approximated by the git log -L analogy. Behavior around output_format and repo is not explained, leaving meaningful gaps for an agent.

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

Parameters3/5

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

Schema description coverage is 0%, so the description must compensate. It explains location via examples (`path::name` or `path:line`) and shows ref usage with `--ref REF`, but repo and output_format are not described at all. Core parameters are covered, ancillary ones are not.

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

Purpose4/5

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

The description states a specific behavior: follow a code structure backwards through commits, including renames and the introducing commit. The git log -L analogy reinforces the purpose. It is somewhat dense and jargon-heavy, but still distinguishes this from the sibling tools.

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

Usage Guidelines3/5

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

The description implies when to use the tool: when you need history of a structure rather than a plain file or directory. It gives concrete shell invocations, but it does not explicitly compare against siblings or state when not to use it.

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

list_directoriesList DirectoriesB

Skeleton of files or a directory: every structure with path:line, signature or title, a condensed excerpt within the budget. A directory gives the tree with one-line gists. --depth quick is about 300 tokens per file, normal 1500, deep everything with module values whole (files only). Elided content is marked ⟨…⟩ +N; focus reads it. Folders only, no files: the directory hierarchy. In your shell: sct --help (if sct is not on PATH, "/app/.venv/bin/python" -m scantool.cli replaces sct).

ParametersJSON Schema
NameRequiredDescriptionDefault
directoryYes
max_depthNo
respect_gitignoreNo

TDQS

B3.4/5.0
Behavior4/5

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

With no annotations, the description carries the burden, and it does disclose key behavior: returned output is a tree of one-line gists, elided content is marked '⟨…⟩ +N', and depth choices have token budgets. It does not cover side effects, auth, or error behavior, but for a read-only listing tool this is reasonably transparent.

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

Conciseness2/5

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

The text is dense and disorganized, burying the core 'folders only' behavior mid-way and appending shell-specific fallback instructions ('sct --help', venv python path) that are not relevant to MCP invocation. The opening sentence is vague and does not front-load the tool's main purpose.

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

Completeness3/5

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

It covers the main output shape (directory tree, one-line gists) and depth-related behavior, which is useful since there is no output schema. But without parameter documentation for max_depth and respect_gitignore, and without clarifying the first-sentence ambiguity, an agent cannot reliably invoke all parameters correctly.

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

Parameters2/5

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

Schema coverage is 0%, so the description must explain the parameters, but it only hints at directory and refers to '--depth quick/normal/deep', which does not map cleanly to the max_depth integer parameter and could mislead an agent into passing those strings. respect_gitignore is not mentioned at all.

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

Purpose4/5

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

The description identifies the resource as directory hierarchy ('Folders only, no files: the directory hierarchy') and the result as a tree with one-line gists, which is more specific than merely restating the tool name. However, the opening 'Skeleton of files or a directory' blurs whether files are included, and no sibling is named, so it is not a perfect differentiator.

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

Usage Guidelines4/5

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

It gives a clear scope ('Folders only, no files') that tells an agent when this directory-tree tool is appropriate and when it is not, and it explains depth-mode trade-offs in token budgets. It does not explicitly name sibling alternatives like scan_directory or preview_directory, so it stops short of a 5.

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

overlapOverlapA

N branches against one base, each at its own merge-base: structures touched by 2+ branches (marked base(~/+/-) when the base itself changed them since the branches forked), new names introduced independently by 2+ branches, commits two branches share (a stack: overlap between them is expected; the residual beyond their shared commits is what stays), and per branch whether it is already in the base and by which criterion (ancestor / patch-equivalent / tree-equal; patch-equivalence proves it can be deleted, not that its content is in the current tree). Ends with a merge-order hint, not a verdict. The first line names the parts (branches, history, shared, colliding, order) with line counts; --part ID prints one part alone. In your shell: sct overlap <base> <branch>... (if sct is not on PATH, "/app/.venv/bin/python" -m scantool.cli replaces sct).

ParametersJSON Schema
NameRequiredDescriptionDefault
baseYes
kindNo
partNo
pathNo
repoNo
branchesYes
output_formatNotree

TDQS

A4.1/5.0
Behavior5/5

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

No annotations exist, so the description bears full behavioral burden, and it delivers: it explains output parts, line counts, --part behavior, the merge-order hint not being a verdict, and the nuanced meaning of patch-equivalence. It also clarifies what can and cannot be concluded from branch-in-base criteria.

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

Conciseness4/5

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

The description is dense, but each clause carries meaningful information: output parts, inclusion criteria, part filtering, merge-order caveat, and invocation. The structure is front-loaded with the core analysis semantics and ends with practical command details, though the long sentences require careful parsing.

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

Completeness4/5

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

In the absence of an output schema, the description thoroughly explains the return structure and semantics. It covers invocation and core required parameters, but leaves some optional parameters undocumented; this is a gap, not a fatal one, since base and branches suffice for the main use case.

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

Parameters3/5

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

With 0% schema coverage, the description compensates for base, branches, and part by explaining base/merge-base semantics and the --part ID behavior. However, kind, path, repo, and output_format are left undefined, making the parameter documentation incomplete for a tool with seven parameters.

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

Purpose5/5

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

The description states a specific analytical task: comparing N branches against one base at each branch's own merge-base. It enumerates the distinct outputs (touched structures, independently introduced names, shared commits, branch inclusion criteria), clearly distinguishing it as an overlap-analysis tool rather than a generic diff or history tool.

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

Usage Guidelines3/5

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

The shell invocation and the phrase 'N branches against one base' imply when to use this tool, but there is no explicit guidance about when to prefer it over siblings like find_divergence or history. It tells the agent how to run it, but not the conditions that should trigger selection of overlap over alternatives.

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

preview_directoryPreview DirectoryC

No command on a directory = orientation: size and language mix, entry points, hot functions, the call-graph map (~3-5k tokens; for first-time orientation of an unknown codebase, not for targeted questions). Line one lists the answer's parts with their line counts and the form that fetches one part alone. The file tree is the tier below (scan). In your shell: sct <dir> (if sct is not on PATH, "/app/.venv/bin/python" -m scantool.cli replaces sct).

ParametersJSON Schema
NameRequiredDescriptionDefault
partNo
depthNodeep
directoryYes
max_filesNo
max_entriesNo
respect_gitignoreNo

TDQS

C2.5/5.0
Behavior3/5

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

No annotations are provided, so the description must disclose behavior. It mentions the output size (3-5k tokens) and content (parts, line counts, form to fetch one part). However, it does not explicitly state whether the operation is read-only, has side effects, or requires specific permissions. It does give a shell command, which is helpful, but the behavior beyond the output is not fully disclosed.

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

Conciseness2/5

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

The description is verbose and poorly structured. The first sentence is cryptic ('No command on a directory = orientation'), and the information is scattered. It includes a shell command but does not front-load the tool's purpose. It is not efficient.

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

Completeness1/5

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

Given the tool has 6 parameters, no schema coverage, no output schema, and no annotations, the description is severely incomplete. It does not explain how parameters affect the output, what the exact return format is, or how to use the tool beyond a shell command. An agent cannot reliably use this tool based on the description.

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

Parameters2/5

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

Schema description coverage is 0%, so the description must explain the parameters. It does not. The only hint is 'the form that fetches one part alone', which might refer to the 'part' parameter, but it is not explicit. Parameters like depth, max_files, max_entries, respect_gitignore are completely unmentioned.

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

Purpose2/5

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

The description is cryptic and vague. It mentions 'orientation' and lists content like size, language mix, entry points, hot functions, and call-graph map, but does not clearly state that this tool provides an overview of a directory. The phrasing 'No command on a directory = orientation' is confusing and does not clearly differentiate from siblings like scan_directory or list_directories.

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

Usage Guidelines4/5

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

The description explicitly states when to use: 'for first-time orientation of an unknown codebase, not for targeted questions'. It also indicates that for a file tree, one should use 'scan' (likely a sibling), providing clear context and an exclusion. However, it does not name specific sibling tools.

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

resolveResolveA

Translate path:line or path::name from one ref to another: the enclosing structure with start and end at --from, and where it is at --to (same place, renamed with an identical body, or gone, with the nearest names). In your shell: sct resolve <path:line> --from REF or sct resolve <path::name> --from REF --to REF (if sct is not on PATH, "/app/.venv/bin/python" -m scantool.cli replaces sct).

ParametersJSON Schema
NameRequiredDescriptionDefault
repoNo
ref_toNoWORKTREE
locationYes
ref_fromNo
output_formatNotree

TDQS

A3.8/5.0
Behavior4/5

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

With no annotations provided, the description carries the full burden of behavioral disclosure. It does this well by explaining the outcome categories (same place, renamed with identical body, gone with nearest names) and the structure of the result. It does not mention whether the operation is read-only or describe edge-case handling, but the core behavior is clearly disclosed.

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

Conciseness4/5

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

The description is compact and front-loaded: the core definition appears first, followed by concrete invocation examples. No sentence is wasted, though the density of the first sentence might make it slightly harder to parse quickly.

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

Completeness3/5

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

For a tool with no annotations and no output schema, the description covers the main operation and gives usable syntax examples. It is incomplete regarding the repo parameter, output_format values, and exact return shape, which an agent would need for robust invocation.

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

Parameters3/5

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

Schema description coverage is 0%, so the description must compensate. It adds useful meaning for location (path:line or path::name), ref_from (--from REF), and ref_to (--to REF). However, it does not explain repo or output_format at all, leaving two of the five parameters with only their names and defaults as guidance.

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

Purpose5/5

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

The description clearly identifies the verb ('Translate') and resource (path:line or path::name across refs), and specifies the exact operation: locating the enclosing structure at --from and its counterpart at --to. This distinguishes it from the sibling scanning/searching tools, which focus on listing or diffing content rather than ref-to-ref translation.

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

Usage Guidelines3/5

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

Usage is implied through concrete shell examples showing both the path:line and path::name forms. However, there is no explicit statement of when to prefer this tool over siblings like find_divergence or surface, nor any exclusions or prerequisites.

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

scan_diffScan DiffA

Structural diff between refs. One ref = that ref vs the working tree. Two refs = A...B against their merge-base by default (--no-merge-base compares the tips; a note says which). Per file: + added, ~ changed (signature: old → new; or body: N code / M doc lines), = renamed (paired by identical body; children follow a renamed class), - removed; identical signature deltas in 3+ functions fold into one row; new files as skeletons; a + or ~ function says how many other changed functions call it. The coverage line counts files changed without structural rows and names the reason for each. --review appends candidate dead/orphan/drift the changed files introduced; off by default on both doors. ref vs the working tree, or ref vs ref2; review=True appends the review tail. Use instead of git diff for review and 'what changed' questions. In your shell: sct diff <ref> or sct diff <refA> <refB> (if sct is not on PATH, "/app/.venv/bin/python" -m scantool.cli replaces sct).

ParametersJSON Schema
NameRequiredDescriptionDefault
refNoHEAD
ref2No
budgetNo
reviewNo
directoryYes
no_merge_baseNo
output_formatNotree

TDQS

A4/5.0
Behavior5/5

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

With no annotations, the description carries the full burden of behavioral disclosure, and it is remarkably transparent. It discloses merge-base vs tip comparison, the per-file symbol legend, folding of identical deltas, skeleton files, coverage-line behavior, and the review tail with dead/orphan/drift candidates. It even notes that --review is off by default and that a note indicates which comparison mode was used.

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

Conciseness4/5

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

The description is dense and front-loaded, starting with the core purpose and then providing the output legend and shell usage. It earns its length for a complex tool, but there is some redundancy, such as repeating 'ref vs the working tree, or ref vs ref2' and 'review=True appends the review tail.' It is slightly over-packed but still well structured.

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

Completeness3/5

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

For a complex 7-parameter tool with no annotations and no output schema, the description covers the diff semantics and output rows very well. Yet it omits three parameters, including the only required one, directory, plus budget and output_format, leaving an agent with gaps for a correct invocation. The detail elsewhere makes these omissions conspicuous.

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

Parameters3/5

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

Because schema description coverage is 0%, the description must supply parameter meaning, and it does for ref, ref2, no_merge_base, and review. However, budget, directory (the only required parameter), and output_format are never mentioned, so an agent cannot determine their semantics from either the schema or the description. This is a meaningful gap.

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

Purpose4/5

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

The description opens with 'Structural diff between refs,' naming a specific verb and resource, and then explains one-ref vs two-ref semantics precisely. The detailed output legend makes the purpose unmistakable. It does not explicitly differentiate from sibling tools, so it misses the full 5, but the purpose is otherwise very clear.

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

Usage Guidelines4/5

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

The description explicitly says 'Use instead of git diff for review and "what changed" questions,' providing both a use case and an alternative. It also explains when to use one ref vs two refs and how the default merge-base behavior works. It does not enumerate sibling-tool exclusions, but the guidance is strong enough for correct selection.

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

scan_directoryScan DirectoryB

Skeleton of files or a directory: every structure with path:line, signature or title, a condensed excerpt within the budget. A directory gives the tree with one-line gists. --depth quick is about 300 tokens per file, normal 1500, deep everything with module values whole (files only). Elided content is marked ⟨…⟩ +N; focus reads it. A directory: the file tree with one-line gists per file, code health and churn labels; ref= reads it at a git ref. Replaces Glob/ls for all file types. In your shell: sct scan <dir> (if sct is not on PATH, "/app/.venv/bin/python" -m scantool.cli replaces sct).

ParametersJSON Schema
NameRequiredDescriptionDefault
refNo
modeNobalanced
deltaNo
depthNo
callerNo
patternNo**/*
directoryYes
max_filesNo
output_formatNotree
exclude_patternsNo
include_metadataNo
respect_gitignoreNo

TDQS

B3.4/5.0
Behavior4/5

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

With no annotations, the description carries the full disclosure burden. It is transparent about key output behaviors: depth-specific token budgets (~300/1500/whole), elision markers (⟨…⟩ +N), one-line gists, code health/churn labels, and reading a specific git ref. It stops short of stating that the operation is read-only, but the core output behavior 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.

Conciseness3/5

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

The description is dense but unstructured, mixing output format, depth rules, elision markers, and a shell command in one unparagraphed block. It repeats the directory-tree statement twice ('A directory gives the tree with one-line gists' vs 'A directory: the file tree with one-line gists per file...'). The shell snippet is useful but tangential, and the prose could be tightened into clearer sections.

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

Completeness2/5

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

For a tool with 12 parameters, no output schema, and no annotations, the description is under-specified. It explains skeleton/tree output and covers `depth` and `ref`, but an agent cannot determine the semantics of `mode`, `delta`, or `caller`, or the allowed values of `output_format`. The lack of return-format guidance beyond the elision markers makes it hard to parse results reliably.

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

Parameters2/5

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

Schema description coverage is 0%, so the description must compensate. It explains `depth` and `ref`, and indirectly hints at `include_metadata` via 'code health and churn labels.' However, it leaves `mode`, `delta`, `caller`, `max_files`, `output_format`, `exclude_patterns`, `respect_gitignore`, and `pattern` unexplained; opaque params like `delta` and `caller` remain ambiguous. The description does not carry the weight needed for this low-coverage schema.

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

Purpose4/5

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

The description states what the tool produces: a structure skeleton with path:line, signature/title, and condensed excerpt, plus a directory tree with one-line gists and metadata labels. It also differentiates itself by claiming to replace Glob/ls for all file types. However, it never explicitly names sibling tools like list_directories or preview_directory, so differentiation relies on inference.

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

Usage Guidelines4/5

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

The description gives a clear context of use: it replaces Glob/ls for all file types, signaling when an agent should reach for this rather than a simple listing. It also offers depth-mode and ref options as practical usage hints. Yet it provides no explicit 'when not to use' guidance or direct comparison to sibling tools such as scan_file_content or preview_directory.

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

scan_fileScan FileB

Skeleton of files or a directory: every structure with path:line, signature or title, a condensed excerpt within the budget. A directory gives the tree with one-line gists. --depth quick is about 300 tokens per file, normal 1500, deep everything with module values whole (files only). Elided content is marked ⟨…⟩ +N; focus reads it. One file; budget=1500 for exploration, 300 for a quick look; focus='name' (or 'Class.method') reads one node verbatim instead of guessing line ranges, body_only=True without the file outline; ref= reads it at a git ref. May append a self-levelling CONNECTIVITY note (candidate dead/orphan/drift across the corpus, silent when clean). In your shell: sct scan <path> or sct focus <path> <name> (if sct is not on PATH, "/app/.venv/bin/python" -m scantool.cli replaces sct).

ParametersJSON Schema
NameRequiredDescriptionDefault
refNo
modeNobalanced
deltaNo
depthNo
focusNo
budgetNo
callerNo
condenseNo
body_onlyNo
file_pathYes
output_formatNotree
show_complexityNo
show_decoratorsNo
show_docstringsNo
show_signaturesNo
include_metadataNo

TDQS

B3.3/5.0
Behavior4/5

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

With no annotations, the description carries the behavioral burden and does a substantial job: it discloses output shape, token budgets per depth, elision marker semantics, focus/body_only behavior, and the optional CONNECTIVITY note. It leaves some behaviors like mode/delta/condense/output_format unexplained, but the core scanning behavior is well disclosed.

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

Conciseness3/5

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

The description packs a lot of useful information but does so as one dense run-on paragraph with semicolons. It front-loads the main purpose, yet the lack of structure makes the many details harder to parse; every sentence is informative, but the format is not optimized for an agent scanning the text.

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

Completeness3/5

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

For the required file_path and the main optional parameters, the tool is well specified with budgets, focus semantics, ref handling, and elision behavior. However, with 16 parameters, zero schema descriptions, and no output schema, the many unmentioned toggles leave the definition incomplete for full correct invocation across all options.

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

Parameters2/5

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

Schema description coverage is 0%, so the description must compensate. It does add meaning for file_path, depth, budget, focus, body_only, and ref, but 16 parameters exist and most are never explained: mode, delta, condense, caller, output_format, show_complexity, show_decorators, show_docstrings, show_signatures, and include_metadata are all absent from the description.

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

Purpose4/5

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

The description clearly states what the tool does: it produces a skeleton of a file or directory with path:line, signatures/titles, and budgeted excerpts. It is concrete about the resource and result, but it does not explicitly differentiate itself from sibling tools like scan_file_content or scan_directory, even though it also handles directories despite the 'file' name.

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

Usage Guidelines3/5

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

The description gives practical guidance: budget=1500 for exploration, 300 for a quick look, focus for reading a single node, body_only to suppress the outline, and ref for git refs. However, it does not name alternatives or exclusion conditions, so an agent has to infer when scan_file_content or scan_directory would be more appropriate.

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

scan_file_contentScan File ContentA

Skeleton of files or a directory: every structure with path:line, signature or title, a condensed excerpt within the budget. A directory gives the tree with one-line gists. --depth quick is about 300 tokens per file, normal 1500, deep everything with module values whole (files only). Elided content is marked ⟨…⟩ +N; focus reads it. Content given directly (remote files, APIs, a git blob, stdin), same budget/depth and focus as scan_file. In your shell: sct scan - --as <path> or sct focus - --as <path> <name> (if sct is not on PATH, "/app/.venv/bin/python" -m scantool.cli replaces sct).

ParametersJSON Schema
NameRequiredDescriptionDefault
modeNobalanced
depthNo
focusNo
budgetNo
contentYes
condenseNo
filenameYes
body_onlyNo
output_formatNotree
show_complexityNo
show_decoratorsNo
show_docstringsNo
show_signaturesNo
include_metadataNo

TDQS

A3.7/5.0
Behavior4/5

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

With no annotations, the description carries the full burden. It discloses budget behavior (quick ~300 tokens, normal 1500, deep everything), elision marking (⟨…⟩ +N), focus behavior, and the fact that content can be piped via stdin. It also explains the CLI invocation fallback. This is substantial behavioral context beyond the schema. However, it doesn't disclose side effects (likely none) or error conditions, and the 'same budget/depth and focus as scan_file' reference assumes knowledge of another tool.

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

Conciseness3/5

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

The description is dense and information-rich, but it's a single run-on paragraph that mixes conceptual explanation with CLI usage examples. The most important distinction (content given directly) appears mid-paragraph rather than front-loaded. The CLI invocation details are useful but could be separated or condensed. Every sentence earns its place, but the structure could be improved.

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

Completeness3/5

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

For a tool with 14 parameters, no annotations, and no output schema, the description is incomplete. It explains the core scanning behavior and budget/depth semantics, but doesn't explain what output_format options exist, what mode means, what condense does, or what the return structure looks like. The sibling tools (scan_file, scan_directory) suggest this is part of a family, and the description references scan_file's behavior, but an agent couldn't confidently set all 14 parameters correctly based on this description alone.

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

Parameters3/5

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

Schema description coverage is 0%, so the description must compensate. It explains depth values (quick/normal/deep) and budget implications, and mentions focus reads elided content. It also explains the content and filename parameters implicitly via the stdin example. However, 14 parameters exist and many (mode, condense, body_only, output_format, show_complexity, show_decorators, show_docstrings, show_signatures, include_metadata) are not explained at all. The description covers maybe 4 of 14 parameters, so it partially compensates but leaves most parameters undocumented.

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

Purpose4/5

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

The description states a specific verb ('scan') and resource ('file content' or directory), and distinguishes itself from scan_file by handling content given directly (remote files, APIs, git blob, stdin) rather than paths. However, it doesn't explicitly name the sibling it differs from, and the opening 'Skeleton of files or a directory' is somewhat ambiguous about whether this tool handles directories (which scan_directory likely does).

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

Usage Guidelines4/5

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

The description gives clear context for when to use this tool: when content is provided directly (remote files, APIs, git blob, stdin), and even provides shell command examples. It implies the alternative (scan_file) for path-based scanning, but doesn't explicitly state 'use scan_file for paths' or list exclusions. The sibling list includes scan_file and scan_directory, so the differentiation is mostly implicit.

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

search_structuresSearch StructuresA

Text across a directory (or one file) with structural context: each hit shows its enclosing structure, plus leads to where matched names are defined; when no lead exists it says so. --names matches structure names instead of text, and an empty answer names the paths that match. The pattern is a Python regex; grep's \| is read as alternation with a note. --type filters which structures are reported; --decorator RE (with --names) keeps structures with a matching decorator and answers one row per structure, decorators on the row. 40 structures per page, --limit/--offset for the rest, and the page is stated. content_pattern finds text with its enclosing function/class/section plus leads to definitions; name_pattern/type_filter/has_decorator find structures; ref= searches at a git ref. Best first call for a targeted question; use instead of Grep. In your shell: sct search <dir> <pattern> (if sct is not on PATH, "/app/.venv/bin/python" -m scantool.cli replaces sct).

ParametersJSON Schema
NameRequiredDescriptionDefault
refNo
limitNo
offsetNo
directoryYes
type_filterNo
name_patternNo
has_decoratorNo
output_formatNotree
min_complexityNo
content_patternNo
include_metadataNo

TDQS

A3.8/5.0
Behavior4/5

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

With no annotations, the description carries the full behavioral burden and does a good job: it discloses pagination at 40 per page, states the page is reported, explains edge cases (no lead, empty match answer), and documents Python regex semantics including grep alternation. It doesn't cover auth requirements or failure modes, but for a search tool the disclosed behavior is substantial.

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

Conciseness4/5

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

The description is dense but not padded; the core purpose is front-loaded and every subsequent clause adds actionable detail about modes, regex behavior, pagination, and invocation. It reads as a long run-on block rather than structured sections, but for a tool with 11 parameters the length is mostly earned.

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

Completeness3/5

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

The core search behavior, parameter mappings, and pagination are covered well, and there is enough detail for a first targeted code-search call. Yet with no output schema and 0% schema-description coverage, the complete omission of output_format, min_complexity, include_metadata, and type_filter allowed values leaves meaningful gaps.

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

Parameters3/5

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

Schema description coverage is 0%, so the description needs to compensate, and it maps many parameters: --names/name_pattern, --type/type_filter, --decorator/has_decorator, content_pattern, ref, limit, and offset. However, output_format, min_complexity, and include_metadata are never explained, and the CLI flag names require the agent to map them to schema property names.

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

Purpose4/5

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

The first sentence clearly states the tool searches text across a directory with structural context, and later sentences distinguish text search from structure-name search. It doesn't explicitly name a sibling as the alternative, but it does position itself as the best first call and tells the agent to use it instead of Grep, which differentiates it from a plain text search tool.

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

Usage Guidelines4/5

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

The description says 'Best first call for a targeted question; use instead of Grep' and explains the main modes (content search vs structure search vs git ref), giving an agent a clear sense of when to invoke it. It doesn't provide negative usage guidance or explicitly contrast with sibling tools like scan_file_content, so it stops short of full exclusions.

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

surfaceSurfaceA

The public surface of a package directory at a ref: every exported name with its signature, how it is exported and where it is defined. Each language applies its own rule: Python's all, lazy tables and re-export chains; Rust's pub and lib.rs re-exports; TypeScript's index exports; Go's exported identifiers; visibility keywords elsewhere; a namespace or module is looked through. --against REF prints the surface diff; the header states the direction (A → B) and names its parts (added, changed, moved, removed) with line counts; --part ID prints one part alone. In your shell: sct surface <package-dir> or sct surface <package-dir> --against REF (if sct is not on PATH, "/app/.venv/bin/python" -m scantool.cli replaces sct).

ParametersJSON Schema
NameRequiredDescriptionDefault
refNo
partNo
againstNo
package_dirYes
output_formatNotree

TDQS

A4/5.0
Behavior5/5

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

With no annotations, the description carries the full behavioral burden and meets it: it states exactly what is inspected, how each language's export rules are applied, what the diff header contains (direction, parts, line counts), and what `--part` prints. It also makes the read-only nature clear by describing printed output, so the agent can infer no destructive side effects.

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

Conciseness4/5

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

The description is dense but front-loaded, leading with the core purpose before adding language rules, flags, and shell invocation. Every sentence contributes, though the invocation fallback sentence is slightly verbose for a tool definition.

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

Completeness3/5

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

For a 5-parameter tool with no output schema and no annotations, the description explains the primary output and main modes, but it leaves `ref` and `output_format` underspecified. An agent can make a correct basic call but may mis-specify output formats or the ref parameter.

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

Parameters3/5

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

Schema description coverage is 0%, so the description must supply parameter meaning; it does for package_dir, --against, and --part, but leaves `ref` and `output_format` undocumented. The `ref` property is only vaguely implied by 'at a ref,' and `output_format` has no explanation at all.

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

Purpose4/5

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

The description opens with a specific resource ('public surface of a package directory at a ref') and enumerates the output ('every exported name with its signature, how it is exported and where it is defined'), making the purpose clear. It does not explicitly distinguish itself from sibling tools like scan_diff or find_divergence, so differentiation is implicit rather than stated.

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

Usage Guidelines4/5

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

It gives concrete invocation patterns (`sct surface <package-dir>`, `--against REF`, `--part ID`) and explains the diff and part-printing modes, giving a clear sense of when each mode is appropriate. It does not, however, state exclusions or when to prefer a sibling tool.

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

Tool Schema Changelog

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

  1. 5 tool updatesv0.28.0
    • Changedoverlap1 field changed
      • addedInput schema / properties / part
        Added value: +{
        +  "default": "",
        +  "type": "string"
        +}
    • Changedpreview_directory1 field changed
      • addedInput schema / properties / part
        Added value: +{
        +  "default": "",
        +  "type": "string"
        +}
    • Changedscan_file1 field changed
      • addedInput schema / properties / body_only
        Added value: +{
        +  "default": false,
        +  "type": "boolean"
        +}
    • Changedscan_file_content1 field changed
      • addedInput schema / properties / body_only
        Added value: +{
        +  "default": false,
        +  "type": "boolean"
        +}
    • Changedsurface1 field changed
      • addedInput schema / properties / part
        Added value: +{
        +  "default": "",
        +  "type": "string"
        +}
  2. 9 tool updatesv0.26.0
    • Addedcallers
    • Addedhistory
    • Addedoverlap
    • Addedresolve
    • Changedscan_diff4 fields changed
      • addedInput schema / properties / no_merge_base
        Added value: +{
        +  "default": false,
        +  "type": "boolean"
        +}
      • addedInput schema / properties / output_format
        Added value: +{
        +  "default": "tree",
        +  "type": "string"
        +}
      • addedInput schema / properties / ref2
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null
        +}
      • addedInput schema / properties / review
        Added value: +{
        +  "default": false,
        +  "type": "boolean"
        +}
    • Changedscan_directory1 field changed
      • addedInput schema / properties / ref
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null
        +}
    • Changedscan_file1 field changed
      • addedInput schema / properties / ref
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null
        +}
    • Changedsearch_structures1 field changed
      • addedInput schema / properties / ref
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null
        +}
    • Addedsurface
  3. 4 tool updatesv0.23.0
    • Changedscan_directory2 fields changed
      • addedInput schema / properties / caller
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null
        +}
      • addedInput schema / properties / include_metadata
        Added value: +{
        +  "default": true,
        +  "type": "boolean"
        +}
    • Changedscan_file2 fields changed
      • addedInput schema / properties / caller
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null
        +}
      • addedInput schema / properties / include_metadata
        Added value: +{
        +  "default": true,
        +  "type": "boolean"
        +}
    • Changedscan_file_content6 fields changed
      • addedInput schema / properties / budget
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "integer"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null
        +}
      • addedInput schema / properties / condense
        Added value: +{
        +  "default": true,
        +  "type": "boolean"
        +}
      • addedInput schema / properties / depth
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null
        +}
      • addedInput schema / properties / focus
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null
        +}
      • addedInput schema / properties / include_metadata
        Added value: +{
        +  "default": true,
        +  "type": "boolean"
        +}
      • addedInput schema / properties / mode
        Added value: +{
        +  "default": "balanced",
        +  "type": "string"
        +}
    • Changedsearch_structures3 fields changed
      • addedInput schema / properties / include_metadata
        Added value: +{
        +  "default": true,
        +  "type": "boolean"
        +}
      • addedInput schema / properties / limit
        Added value: +{
        +  "default": 40,
        +  "type": "integer"
        +}
      • addedInput schema / properties / offset
        Added value: +{
        +  "default": 0,
        +  "type": "integer"
        +}
  4. 8 tool updatesv0.20.1
    • Changedfind_divergence4 fields changed
      • addedInput schema / additionalProperties
        Added value: +false
      • addedInput schema / properties / directory / description
        Added value: +"Root directory to audit"
      • addedInput schema / properties / max_findings / description
        Added value: +"Cap on the number of findings shown (default: 20)"
      • addedInput schema / properties / respect_gitignore / description
        Added value: +"Respect .gitignore patterns (default: True)"
    • Changedlist_directories1 field changed
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedpreview_directory1 field changed
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedscan_diff1 field changed
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedscan_directory1 field changed
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedscan_file1 field changed
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedscan_file_content1 field changed
      • addedInput schema / additionalProperties
        Added value: +false
    • Changedsearch_structures1 field changed
      • addedInput schema / additionalProperties
        Added value: +false
  5. 8 tool updatesv0.19.4
    • First observedfind_divergence
    • First observedlist_directories
    • First observedpreview_directory
    • First observedscan_diff
    • First observedscan_directory
    • First observedscan_file
    • First observedscan_file_content
    • First observedsearch_structures

TDQS

B3.3/5.0

Scored across 13 tools

Disambiguation2/5

Multiple tools share nearly identical opening descriptions: scan_file, scan_file_content, scan_directory, list_directories, and preview_directory all describe skeleton/tree output for files or directories. An agent must read carefully to distinguish file path vs. direct content vs. directory vs. folders-only vs. orientation, so boundaries are unclear.

Naming Consistency3/5

Most names follow a verb_noun snake_case pattern (scan_file, scan_directory, search_structures, list_directories), but several tools break it with noun-only or verb-only names (history, surface, overlap, callers, resolve). The naming is readable and consistently snake_case, yet the conventions are mixed.

Tool Count4/5

At 13 tools, the count is within the well-scoped range and broadly justified by the server's wide static-analysis purpose. However, several scanning variants overlap in functionality, making the set feel slightly larger than necessary.

Completeness5/5

The tool surface is comprehensive for a read-only code scanner: it covers scanning, search, callers, structural diff, history, resolve, public API surface, branch overlap, and divergence hints. There are no obvious dead ends or missing operations for the stated purpose.

Maintenance

ActivityActive
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    A
    quality
    D
    maintenance
    Enables AI assistants to understand and navigate codebases through structural analysis. Provides code mapping, symbol search, and impact analysis using ast-grep for accurate parsing of Python, JavaScript, TypeScript, and Go projects.
    4
    52
    MIT
  • A
    license
    A
    quality
    D
    maintenance
    Analyzes codebases and extracts all symbols (functions, classes, methods, interfaces, etc.) from 10+ programming languages into LLM-optimized markdown format. Enables AI assistants to understand entire project structures efficiently without processing full source code.
    2
    5 npm
    MIT