django-chainsaw-mcp
This MCP server statically analyzes a Django (plus some FastAPI/SQLAlchemy/Python) project to surface bugs, risks, and performance issues before runtime.
Run a combined
checkthat executes all applicable analyses and returns severity-sorted findings.Inspect project and model structure:
project_info,list_models,explain_model,delete_impact, andwhat_happens_onsignal chains.Detect query performance problems: N+1 in templates and DRF serializers, queries in loops, unused eager loading, missing indexes, and endpoint query costs.
Assess migrations and deploy safety:
migration_risk,deploy_safety, and whether code still references removed fields.Find security and tenant-isolation issues: unscoped queries/IDOR, open endpoints, FastAPI exposure, and amplification attacks.
Audit correctness and consistency: race conditions, bypassed bulk-write effects, escaping side effects, money precision, datetime naivety, choice typos, dangling references, multiplied aggregates, and Celery arguments.
Compare API contracts to catch breaking serializer changes via
api_contractandapi_contract_check.Generate fix suggestions grouped by safety (mechanical/generated/advisory) and produce request-impact or HTML report views.
Profile non-Django Python projects for async blocking, SQLAlchemy N+1, FastAPI exposure, and framework composition.
Analyses Django projects through the app registry: inspects models and relations, calculates delete impact, finds N+1 queries in templates and DRF serializers, rates migration and deploy safety, detects unscoped tenant queries, signal side effects, race conditions, and more.
Reads FastAPI routes to extend analysis beyond Django, helping determine which findings are reachable through API endpoints.
Reads SQLAlchemy models or mappings to provide cross-framework analysis beyond Django's app registry.
Click on "Install 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., "@django-chainsaw-mcpFind risky patterns like N+1 queries and unsafe migrations in my Django project"
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.
django-chainsaw-mcp
An MCP server and CLI that analyses a Django project rather than describing
it. Not what is in here — what will hurt: what a delete takes with it,
which migration breaks the pods still running, which query returns another
tenant's row, what a save() sets off three hops away.
There is no model in the loop. Every answer comes from the AST and Django's own app registry, so the same input gives the same output, and nothing leaves the machine. It is an MCP server so an assistant can ask it questions, and a CLI so CI can gate on the answers.
22 checks: 19 need the app registry (16 Django, three of those DRF as well), one needs only Python, one reads FastAPI, one reads SQLAlchemy. Why this exists →
Install
It has to run in an interpreter that can import your project. Everything
here reads the app registry, which means django.setup(), your settings and
your apps:
/path/to/project/.venv/bin/python -m pip install django-chainsaw-mcpA plain uvx django-chainsaw-mcp starts and then fails every check, because
uvx gives it an isolated environment with no trace of your project. To avoid
installing, hand uv the dependencies instead:
uvx --with-requirements requirements.txt --from django-chainsaw-mcp django-chainsaw checkTwo environment variables point it at the project:
Variable | Example |
|
|
|
|
django-chainsaw project-info proves the setup before anything else, and says
which half is missing. Five minutes end to end →
mcp-name: io.github.syrian963/django-chainsaw-mcp
Related MCP server: graqle
One command
django-chainsaw check --tenant-root myapp.Organisation44 finding(s): 1 critical, 14 high, 29 medium
CRITICAL
--------
[deploy-safety] RemoveField drops 'legacy_code' while code still uses it
shop/0002_remove_product_legacy_code
During a rolling deploy the old pods keep running against the new
schema and will fail.
fix: Ship a release that stops using it, deploy that everywhere,
then ship this migration.Every analysis, merged, worst first, one exit code.
On a pull request
This is the part that decides whether a tool like this survives. Point tenancy
at a five year old project and it returns two hundred candidates; nobody reads
two hundred candidates, somebody adds continue-on-error, and it runs forever
with nobody looking.
django-chainsaw tenancy --since main # only what this branch changed
django-chainsaw tenancy --baseline # everything old, ratcheted
django-chainsaw check --sarif out.json # annotate the diff, on the line--since compares at the merge base, so a branch that is behind main is not
blamed for other people's work. --baseline keeps existing findings in the
report and stops them blocking; anything new fails the build, and fixing an old
one is reported so the number only ever goes down. Findings are fingerprinted on
file plus identity, never the line, so adding an import does not resurrect
twenty findings nobody touched.
--sarif writes the format GitHub and GitLab annotate a pull request with, so
findings land on the line instead of in a log nobody opens.
As an MCP server
claude mcp add django-chainsaw --scope local \
--env DJANGO_CHAINSAW_PROJECT_PATH=/srv/app \
--env DJANGO_CHAINSAW_SETTINGS_MODULE=myproject.settings \
-- /srv/app/.venv/bin/python -m django_chainsaw_mcp.serverAsk it project_info first: the smallest call that proves both the transport
and the Django boot. Five prompts carry the ordering the tools do not —
before_deploy, why_is_this_slow, what_breaks_if_i_delete, triage,
review_this_branch.
Claude Desktop, Cursor, VS Code, Windsurf, Zed, Docker →
Or as one HTML file
django-chainsaw report --out findings.html --title myproject
Grouped by endpoint is the view that matters: which pages carry this, and through what call path. No server, no network, no build step — the CSS, the script and the data are all in the file, so it works from a CI artifact or an email attachment. report.md
The checks
Tool | Answers |
| Does the target project load at all? Run this first when something is broken. |
| Every model with fields, relation kind, direction and |
| Delete one row: what cascades, what blocks, what gets nulled. Transitive. |
| Relation traversals in a template that each cost a query, and the fix. |
| The same across a directory, resolving context from views. |
| Migrations rated: blocks writes, rewrites the table, breaks running code. |
| Is this destructive migration safe to ship yet? |
| Which queries read data the caller may not own? The IDOR shape. |
| What does this save actually trigger? Follows the signal chain. |
| Fields the code filters or sorts on that carry no index. |
| Naive datetimes and field defaults that break when the clock moves. |
| What DRF serializers expose, including what the next migration will add. |
| N+1 in DRF serializers, which is where it lives in an API project. |
| Everything about one model, plus the risks only visible combined. |
| How many queries one request costs, before anybody sends one. |
| What this branch changes about the API, and who it breaks. |
| Mail and tasks fired inside a transaction that can still roll back. |
| Bulk writes that skip everything the |
| Counters read into Python, changed, and saved. Also unsafe upserts. |
| Where a decimal amount stops being exact. |
| What the worker actually receives, and whether it can even be called. |
| Queries written inside a loop, split by which of three fixes applies. |
| Prefetches paid for and then re-queried by the accessor that reads them. |
| Every finding grouped by the entry points that reach it, so the question becomes which endpoint to fix. |
| Literals a field's |
| Counts and sums multiplied by a join across two multi-valued relations. |
| URL names, templates, signal senders and Celery tasks nothing will resolve. |
| Sensitive fields on endpoints anybody can call. |
| Joins and prefetches nothing in the response reads. |
| Run everything that applies, one severity-sorted list, one exit code. |
| Findings turned into code, grouped by how safe each one is to apply. |
Tool | Answers |
| What is this built on? Counted from the project's own imports. |
| Which synchronous call stops the event loop for every request? |
| Endpoints that serialise more than they declare. |
| Relationships loaded one row at a time, including during serialisation. |
| Which endpoint can a stranger use to exhaust the database? |
Plus the resource django://models. check profiles the project first and runs
what applies, and says "does not apply, and here is why" for the rest —
silence would read exactly like a clean result. Nothing about the FastAPI
support imports the project, so those checks run on a checkout with no
dependencies installed at all.
36 of the 37 tools declare readOnlyHint, so a client can stop asking
permission for each call; the exception is api_contract_check with
update=True, which writes the snapshot and says so.
Every tool, argument and output shape →
What it will not tell you
Nothing here executes the target project or reads its data, which buys safety and speed and costs certainty. Every tool states its own blind spots in its own output:
delete_impactdoes not run signals or customdelete()overrides.find_n_plus_onereports candidates; it reads the template and the model graph, not the queryset in the view.migration_riskdoes not know row counts, PostgreSQL version, or deploy strategy.deploy_safetycannot seegetattr(obj, name), runtime SQL, or another repository.CLEARmeans nothing was found here.
A confident wrong answer is worse than an incomplete one. In this kind of tooling the failure mode is not a crash, it is a plausible sentence that sends someone in the wrong direction. limitations.md
What it does to your code
It imports the target project. django.setup() imports your settings and
every app in INSTALLED_APPS, and the checks additionally import the modules
that declare serializers, views and URLs — so anything those do at import time
happens. Do not point this at code you would not run.
It does not run your application: no view, no task, no management command.
One check reads the database, read-only — MigrationLoader reads
django_migrations, and nothing is written.
It writes files only when you ask: fix --write applies the mechanical
class of fix only, and a baseline, a contract snapshot or --sarif write where
you tell them to. Nothing leaves the machine — no network calls, no
telemetry, no uploads.
Documentation
docs/ is the index.
why this exists, three checks worth reading about, and the bar a new one clears | |
five minutes from clone to first finding | |
installing against a real project, Docker, troubleshooting | |
Claude Code, Cursor, VS Code, Windsurf, Zed | |
commands, exit codes, CI | |
every tool, argument and output shape | |
eighteen public projects, what they found in this tool, and the checks that never fired | |
what the analysis cannot see | |
ratcheting, so this survives a legacy codebase | |
suggestions as real code, and which can be applied | |
how it is put together, and why the bootstrap drives the design | |
where the time goes on a large project |
Contributing
workflow, house style, how to run the suites | |
every release, and the reasoning behind the changes | |
what this does to the code you point it at | |
be straight with people and be kind about it |
A proposal for a new check answers four questions, which the issue template asks directly: what the defect looks like as code, how it fails in production, what already finds it, and what it must stay silent on. Two finished features were deleted from this repository after measurement showed they could not tell a real finding from a correct one.
MIT. One process stays bound to the first project it loads, because
django.setup() cannot be undone — run a second instance for a second project.
Available Tools
37 toolsamplificationBRead-onlyIdempotent
Endpoints anyone can call that cost a great deal to answer.
Two facts, each of which is somebody else's finding and neither of which
is wrong alone:
GET /orders has no authentication.
GET /orders issues about 2852 queries per request.
The first is right on a public catalogue. The second, behind a login, is a
backlog item. Together they are one request, from anyone, that costs the
database three thousand queries - and every one of them returns 200, so
nothing in the logs looks like an attack.
The other half is the unbounded list: public, unpaginated, and therefore
the whole table in one request. That is not load, it is exfiltration.
The tools that look for this are DAST scanners; they need the service
running, reachable and holding enough rows for the cost to show. All of it
is in the source. Works on Django (DRF views) and FastAPI.
Args:
search_path: directory to scan. Defaults to the configured project.
| Name | Required | Description | Default |
|---|---|---|---|
| search_path | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the readOnly/idempotent/destructive annotations, the description discloses that the analysis is source-based, works on Django (DRF) and FastAPI, and scans a directory. This adds useful operational context, although it could be clearer that this tool itself is not a live DAST scanner.
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 uses a narrative, examples-heavy style rather than a front-loaded imperative, and it takes several sentences before connecting to the tool's own behavior. Most sentences contribute context, but they could be tightened.
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?
It covers the search path input, supported frameworks, and the vulnerability class, and an output schema exists to explain return values. However, the lack of an explicit statement of what the tool returns/detects and how unsupported projects are handled leaves moderate gaps.
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 schema only provides a nullable string with a default and no description, so the Args line adds real semantic value: search_path is the directory to scan and defaults to the configured project. Complete for a single optional parameter.
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 defines the amplification concept (endpoints anyone can call that cost a great deal) and implies a source scan via search_path, but never states an explicit verb like 'find' or 'scan for amplification vulnerabilities.' It is distinguishable by topic but not clearly articulated as a tool operation.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The mention of DAST scanners needing a running service while 'all of it is in the source' implies this tool is a source-based alternative, but the description does not state when to choose amplification over sibling tools such as open_endpoints or endpoint_cost. The guidance is implicit rather than explicit.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
api_contractARead-onlyIdempotent
The shape every serializer currently promises its clients.
Field names, types, whether each is read only, required, nullable, and what
the nested ones expand to. Resolved from the class definitions, so nothing
needs to run and no request needs to be sent.
Capture this on the branch you already shipped, commit the result, and
api_contract_check will tell a later branch what it broke.
Args:
max_depth: how far to expand nested serializers.
| Name | Required | Description | Default |
|---|---|---|---|
| max_depth | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already mark the tool as read-only, idempotent, and non-destructive, and the description adds meaningful behavioral context: the contract is resolved statically from class definitions, so no code execution or network request is needed. This explains the operational profile beyond what annotations alone 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 description is compact and well-structured: the core purpose comes first, followed by the static-resolution behavior, then the workflow instruction, then the parameter explanation. Every sentence contributes useful information with no filler or 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?
Given the output schema exists and annotations cover safety, the description is sufficient for an agent to understand what the tool returns, why it exists, and how to use it in the branch workflow. The only minor gap is that it does not explicitly say where or how the contract result is emitted, but the output schema partially covers that.
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?
Even though schema description coverage is 0%, the description provides an Args section explaining that max_depth controls how far nested serializers expand, which adds semantic meaning beyond the schema's plain integer type and default value. It could be more precise about valid ranges or edge cases, but for a single optional parameter it is adequate.
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 clearly identifies the tool as capturing the current API contract shape that serializers promise, including field names, types, nullability, and nested expansion. It uses specific language ('Capture this', 'Resolved from the class definitions') that distinguishes it from similarly named siblings like api_contract_check, which is described as the later comparison step.
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 explicit workflow context: run this on the already-shipped branch, commit the result, and then api_contract_check will report what a later branch broke. This clearly implies when to use it and how it relates to the closest sibling, though it does not enumerate exclusions or alternative tools.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
api_contract_checkAIdempotent
What this branch changes about the API, and who it breaks.
Removing a serializer field is a one line diff that reads as tidying up.
The client on a version nobody updated still reads that field. Every tool
that catches this needs the app running: drf-api-checker records real
responses during a test run, OpenAPI diffing needs the schema generated.
Changes come back sorted by who they hurt. Breaking means an existing
client stops working: a field it reads disappears, a field it omits becomes
required, a type or a constraint narrows. Risky means it still parses but
the values may surprise it. Additive means nobody notices.
Args:
snapshot_path: the committed contract to compare against.
update: overwrite the snapshot with the current shape instead of
comparing. Do this once you have decided a change is intended.
max_depth: how far to expand nested serializers.
| Name | Required | Description | Default |
|---|---|---|---|
| update | No | ||
| max_depth | No | ||
| snapshot_path | No | .django-chainsaw-contract.json |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate idempotent and non-read-only behavior, but the description adds useful operational context: 'update' overwrites the snapshot, 'max_depth' controls expansion, and results are sorted by impact. It defines breaking, risky, and additive outcomes clearly. No contradiction with annotations is present.
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 well-structured with a purpose statement and an Args section, but it includes somewhat narrative passages like the serializer field removal example and the drf-api-checker/OpenAPI aside. These add color but are not strictly necessary for selecting or invoking the tool, making it less concise than it could be.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema present and all three parameters documented, the description is largely complete. It explains the comparison semantics, the update mode, and the depth control. The only small gaps are the exact format expected for snapshot_path and any prerequisites for the current API shape to be available, but these are not severe.
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%, but the Args section fully compensates by explaining all three parameters: snapshot_path is the committed contract to compare against, update switches to overwrite mode with a clear caution, and max_depth controls serializer expansion depth. This adds exactly the meaning the schema lacks.
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 clearly communicates that the tool compares API contract snapshots and classifies changes as breaking, risky, or additive. It uses concrete verbs like 'compare' and 'overwrite' in the Args section and describes the resource. However, it does not explicitly differentiate itself from the sibling tool 'api_contract', so an agent may have to infer which one to call.
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 implies this tool is for reviewing contract changes when a branch modifies the API, and it gives explicit guidance that 'update' should only be used once a change is intended. However, it does not directly state when to choose this tool over alternatives like 'api_contract', and the reference to drf-api-checker and OpenAPI diffing is more about other approaches than actual selection criteria.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
blocking_in_asyncARead-onlyIdempotent
Synchronous calls that run on the event loop.
FastAPI runs an `async def` endpoint on the loop itself and a `def`
endpoint in a threadpool. So a blocking call inside `async def` does not
slow one request, it stops every request in the process - invisible at one
request a second, an outage at two hundred.
ruff's ASYNC rules cover open, time.sleep and subprocess inside an async
function. This adds the two that matter more: a synchronous database call,
which is the common one, and a blocking call reached through another
project function, where nothing at the call site looks blocking. The second
comes back with the path that reaches it.
Needs no Django. A `def` endpoint is never reported, because blocking in a
threadpool is fine and telling somebody to make it async causes the outage.
Args:
search_path: directory to scan. Defaults to the configured project.
follow_calls: also report blocking reached through a project function.
max_depth: how many calls deep to follow.
| Name | Required | Description | Default |
|---|---|---|---|
| max_depth | No | ||
| search_path | No | ||
| follow_calls | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Well beyond the readOnly/idempotent annotations, the description explains why blocking matters (it stalls every request in the process), what analysis behavior to expect (following calls through project functions and returning the path that reaches a blocking call), and constraints such as no Django requirement. There is no contradiction with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The text is dense but organized: a summary sentence, a brief rationale, a coverage contrast, and an Args block. Each sentence contributes either selection guidance, behavioral expectations, or parameter semantics, with 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?
Given that an output schema exists and annotations already convey the safety profile, the description covers purpose, usage conditions, behavioral edge cases, and all three parameters. Nothing needed to invoke or interpret the tool correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description carries param documentation, and the Args block succeeds: search_path defines the directory and its project default, follow_calls defines the indirect-call coverage, and max_depth defines call-depth. This adds meaning well beyond the schema's types and defaults.
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 immediately scopes the tool to synchronous/blocking calls executed on the event loop, and then specifies the exact patterns it detects: synchronous database calls and blocking calls reached through project functions. It further clarifies what is out of scope (`def` endpoints), giving an agent a precise resource+verb pair that is distinct from sibling static-analysis tools.
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 concrete conditions: FastAPI async endpoints versus threadpool `def` endpoints, and explicitly says `def` endpoints are never reported because blocking there is acceptable. It also contrasts the tool with ruff's ASYNC rules, stating what coverage this tool adds, so an agent can decide when this tool rather than related checks applies.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
bypassed_effectsARead-onlyIdempotent
Bulk writes that skip everything the model's save() chain promised.
what_happens_on says saving an Order creates an Invoice. That is true for
order.save() and false for Order.objects.bulk_create(), .bulk_update() and
.update(): they go straight to SQL, so no save() override runs and no
pre_save/post_save receiver fires. Django documents this in one sentence
per method; nothing at the call site says it.
The finding is not "bulk_create bypasses signals" but this call, on this
model, skips these named effects - the receivers, the overridden save(),
the models that would have been written, transitively. A cache that never
gets invalidated and a search index that quietly drifts are both this.
Only models whose chain does something are reported. QuerySet.delete() is
not listed: Django sends delete signals per object, so that chain fires.
Args:
search_path: directory to scan. Defaults to the project root.
model: restrict to one "app_label.ModelName".
| Name | Required | Description | Default |
|---|---|---|---|
| model | No | ||
| search_path | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description discloses that only models with meaningful chains are reported, that QuerySet.delete is excluded, and why. It also describes the real-world consequences (stale cache, drifting search index), which adds value beyond the readOnly/idempotent/destructive annotations. No contradiction.
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 longer than average but front-loads the core idea, then adds necessary context, exclusions, and an Args section. The examples of cache invalidation and search-index drift earn their place, though a sentence or two could be trimmed.
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 code-analysis tool with an output schema and safety annotations, the description covers scope, exclusions, and parameters. It sufficiently prepares an agent to call it correctly, though it relies on the output schema for result-shape details.
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%, but the Args section compensates by explaining search_path defaults to project root and model restricts to an app_label.ModelName. It doesn't explicitly state that omitting model scans all models, but 'restrict to one' implies it.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description identifies the resource as bulk-write calls that bypass the model save() chain and explains the finding scope, contrasting it with what_happens_on. It lacks an explicit verb like 'find' or 'scan' in the opening sentence, but the content makes the purpose clear.
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 when the tool is relevant: for bulk_create, bulk_update, and update calls on models whose save chain has effects, and explicitly excludes QuerySet.delete() because delete signals fire. It references what_happens_on to set context, though it does not give an explicit 'use this instead of X' rule.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
celery_argumentsARead-onlyIdempotent
Model instances handed to Celery tasks, and calls whose arity is wrong.
order = Order.objects.get(pk=pk)
send_confirmation.delay(order)
The worker does not get that order. It gets whatever the serialiser made
of it, rehydrated later on another machine: the row may have changed in
between, the whole object crosses the broker, and under the JSON
serialiser - the default since Celery 4 - it may not encode at all. Pass
the primary key and let the task load it.
Also reports a dispatch whose argument count cannot match the task.
Celery's strict_typing catches that at call time, which for a nightly job
or an error branch means in production, months later.
flake8-pie has Celery lints for names, crontab arguments and expirations.
None of them look at what is passed.
A dispatch is only checked when the name resolves to a task this project
defines, through the file's own imports - matching on the bare name
reported unrelated objects of the same name against the task's signature.
Args:
search_path: directory to scan. Defaults to the configured project.
| Name | Required | Description | Default |
|---|---|---|---|
| search_path | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the readOnly/idempotent annotations, the description explains that the tool reports two distinct issue types and discloses an important limitation: matching on the bare name may report 'unrelated objects of the same name against the task's signature.' It also clarifies that checks depend on import resolution, giving the agent a realistic sense of the tool's coverage and potential false positives.
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 purpose and includes an Args section, but the middle paragraphs contain a lengthy narrative example and Celery background that could be shortened. The flake8-pie comparison is useful context, but the overall length is higher than necessary for an agent selecting and invoking the tool.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's complexity and that an output schema exists (so return values are presumably defined), the description covers the main behavior, the search_path parameter's meaning and default, and a notable limitation. An agent has enough information to invoke it correctly and interpret its scope, though it could state the output format or expected result types explicitly if the output schema were not present.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema provides only the name, type, and default for search_path; the description compensates by stating it is 'a directory to scan' and defaults to the configured project. This is brief but sufficient for an optional single parameter, even though schema coverage is 0%.
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 sentence, 'Model instances handed to Celery tasks, and calls whose arity is wrong,' clearly identifies the two problem categories the tool detects. The title and the rest of the description confirm it is a static analysis tool, though it lacks an explicit verb like 'reports' or 'scans.'
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 indirectly signals when to use this tool by contrasting with flake8-pie: 'None of them look at what is passed.' It also describes a search_path default and the condition that a dispatch is 'only checked when the name resolves to a task this project defines,' which gives context for effective use. However, it never explicitly states when to prefer this tool over sibling tools or provides exclusion criteria.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
checkARead-onlyIdempotent
Run every analysis and return one severity-sorted list.
The single call to reach for on an unfamiliar project. It runs the checks
whose findings are defects, merges them, and sorts by severity, instead of
making you know which of a dozen tools to ask for.
A check that fails to run is listed in `checks_failed` rather than counted
as clean.
This is the one slow call here - a minute or more on a large project - and
it reports progress as each check starts, so a client can name the check
that is running instead of showing nothing for a minute.
Args:
tenant_root: the model that owns data, for the ownership check.
only: run just these checks.
skip: run everything except these.
| Name | Required | Description | Default |
|---|---|---|---|
| only | No | ||
| skip | No | ||
| tenant_root | No | auth.User |
Output Schema
| Name | Required | Description |
|---|---|---|
| ok | No | present and false only when the run could not happen at all |
| note | No | |
| error | No | |
| findings | No | |
| checks_run | No | per check: whether it ran, and how many it produced |
| frameworks | No | what was detected in the project, and its version |
| by_severity | No | |
| checks_failed | No | checks that raised. These are not clean results - a project with a failed check has fewer findings than it has problems. |
| finding_count | No | |
| checks_not_applicable | No | check name to the reason it does not apply here |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the readOnly/idempotent/destructive annotations, the description adds important behaviors: failed checks appear in 'checks_failed' rather than being treated as clean, this is 'the one slow call here,' and it 'reports progress as each check starts.' These details materially change how a client should call and present the 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?
The description is compact and front-loaded: purpose first, use case second, distinctive failure/perf behavior third, and parameter meanings last. No sentence is wasted; each adds either routing, behavioral, or parameter value.
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 an aggregate tool with three optional parameters and an output schema, the description covers what the tool does, when to use it, how failures are represented, performance expectations, progress reporting, and all parameters. The existence of an output schema excuses it from detailing return structure.
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 burden, and it does: 'tenant_root: the model that owns data, for the ownership check,' 'only: run just these checks,' and 'skip: run everything except these.' It gives each parameter purpose beyond the raw names, though it could be more explicit that only/skip expect sibling check names.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Run every analysis and return one severity-sorted list.' It explicitly frames the tool as the aggregate entry point that 'runs the checks whose findings are defects, merges them, and sorts by severity,' which distinguishes it from the many sibling analysis tools without requiring the agent to know which one 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?
It gives a clear use context: 'The single call to reach for on an unfamiliar project' and says it exists 'instead of making you know which of a dozen tools to ask for.' It does not explicitly enumerate when-not-to-use or name a specific alternative, but the guidance is strong enough for an agent to select it as the broad entry point.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
choice_typosARead-onlyIdempotent
Literals compared against a field whose choices will never match them.
STATUS = [("canceled", "Canceled"), ...]
Order.objects.filter(status="cancelled")
Two Ls. Valid Python, valid SQL, zero rows, no exception, wrong forever.
Nothing in Django objects: `choices` is checked by `full_clean()`, which a
queryset never calls and `create()` never calls either - so the write side
is worse, and puts a value in the column the application does not believe
exists.
No existing tool finds this: django-stubs types the field as `str` rather
than a Literal union of its choices, so mypy is satisfied, and the DJ rules
do not read the model registry.
Only literals are checked - an enum member is the spelling that cannot go
wrong - and only equality and `in`, because `iexact` can legitimately match
a differently spelled value. `order.status == "..."` names no model, so it
is reported only when the literal is wrong for every model with a field of
that name.
Args:
search_path: directory to scan. Defaults to the configured project.
include_tests: also scan test files.
| Name | Required | Description | Default |
|---|---|---|---|
| search_path | No | ||
| include_tests | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare read-only/idempotent behavior, and the description adds substantial non-obvious context: the write path is worse because `create()` bypasses `full_clean()`, mypy is satisfied by `str` typing, and the typo silently yields zero rows without exceptions. This goes well beyond the structured annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The definition is long but every section earns its place: concrete example, root-cause explanation, matching boundaries, and Args. Core behavior is front-loaded before examples and parameter details, making it easy to scan.
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?
It gives the full detection rules, explains why no other tool catches the defect, covers the write-side danger, and documents all parameters. An output schema exists, so omitting return-format details is appropriate.
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 by explaining `search_path` as the directory to scan with a project default and `include_tests` as toggling test-file scanning. The two Args lines are concise but cover both parameters meaningfully.
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 sentence precisely describes what the tool does: detecting string literals compared against Django field choices that can never match. The included example and the claim that no existing tool finds this clearly distinguish it from sibling linters.
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 explicit detection boundaries: only literals, only equality and `in`, not `iexact`, and not enum members, plus a false-positive rule for model-less comparisons. It does not name sibling alternatives directly, but the when/when-not guidance is otherwise clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
dangling_referencesARead-onlyIdempotent
URL names and template names that nothing will resolve.
return redirect("order-detial")
return render(request, "shop/order_detial.html", context)
{% url 'shop:order-detial' order.pk %}
Each of these is resolved while serving a request and checked by nothing
before then. Rename a URL pattern or move a template and they keep
importing, keep passing every test that does not walk that branch, and
raise NoReverseMatch or TemplateDoesNotExist the first time a real person
opens the page - on the path nobody was watching.
Both sides use the project's own machinery: names come from every URLconf
in the project walked through each include(), so namespaces are real and a
second URLconf served by host is not mistaken for a missing one; templates
go through get_template(), so the project's loaders decide.
`by_name` groups the findings, because one missing name used in
thirty-five places is one problem.
Args:
search_path: directory to scan. Defaults to the configured project.
include_templates: also read `{% url %}`, `{% include %}` and
`{% extends %}` out of the templates.
include_tests: also scan test modules. Off by default: tests run under
their own settings, so a name missing from these ones may be
registered under theirs.
| Name | Required | Description | Default |
|---|---|---|---|
| search_path | No | ||
| include_tests | No | ||
| include_templates | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description goes well beyond the read-only/idempotent annotations by explaining how resolution is performed: URLconfs are walked through include() with real namespace handling, templates go through get_template() with project loaders, and findings are grouped by name via by_name. This is valuable behavioral detail beyond what the annotations state.
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 examples and grouping rationale each add value. The description is a bit longer than strictly necessary, but its paragraph structure keeps it digestible and focused.
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 description covers purpose, usage context, behavioral details, parameter semantics, and grouping behavior. With an output schema present and annotations already declaring safety properties, nothing essential is missing for an agent to select and invoke the tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, but the description compensates by documenting all three parameters with meaningful details, especially search_path defaulting to the current working directory and the include_tests/include_templates toggles. The parameter descriptions are terse and somewhat predictable from their names, but they fill 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 opening phrase 'URL names and template names that nothing will resolve' states the resource and what condition the tool identifies, and the examples clarify that it finds references that will raise NoReverseMatch or TemplateDoesNotExist. It is clear but does not explicitly differentiate itself from sibling tools such as scan_templates.
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 a strong usage context: after renaming a URL pattern or moving a template, these references keep passing tests until a real request hits that branch. It implies when to use the tool, but it does not explicitly name alternatives 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.
datetime_auditARead-onlyIdempotent
Naive datetimes in code, and ambiguous defaults on model fields.
With USE_TZ on, code that builds its own datetimes with datetime.now() or
from parts produces naive values, and mixing them with the aware ones the
ORM returns either raises or compares against the wrong instant. It is
invisible for ten months and shows up on the two nights the clock moves.
Also reports model fields whose default is naive, whose default was
evaluated once at import time, or that set auto_now and auto_now_add
together.
Args:
search_path: directory to scan. Defaults to the project path.
| Name | Required | Description | Default |
|---|---|---|---|
| search_path | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the readOnly/idempotent annotations, the description discloses the exact categories of issues checked (naive datetimes, naive defaults, import-time defaults, auto_now/auto_now_add together). It explains the subtle behavior of the bug (invisible for ten months, surfacing during DST transitions), adding judgment context without contradicting any annotation.
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 organized into topic, why-it-matters, and an explicit Args section. Each sentence either defines scope or provides a decision-relevant detail; the length is justified, though the DST narrative is slightly more expansive than strictly necessary.
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 optional parameter and an output schema that likely describes results, the description covers the resource, the trigger conditions, the precise checks, and the parameter semantics. Nothing an agent needs to correctly select and call this tool is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With 0% schema description coverage, the description fully compensates: it names the search_path parameter, says it's a directory to scan, and gives its default ('the project path') – more specific than the schema's 'default: null'.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a clear noun-phrase summary of the exact problem domain – naive datetimes in code and ambiguous model field defaults – and then elaborates with specifics: builds its own datetimes from datetime.now()/parts, naive defaults, import-time defaults, and auto_now with auto_now_add. This provides a specific verb ('reports') and resource scope that distinctively separates it from the many sibling audit tools.
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 concrete context: 'With USE_TZ on' and the long-term invisibility of the bug, making clear when this audit is relevant. It does not name alternatives or exclusions, but the specificity of datetime/model field issues and the sibling list establish when to choose it.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
defeated_prefetchesARead-onlyIdempotent
Relations that were prefetched and then re-queried anyway.
A prefetched related manager answers `.count()`, `.exists()`, `.all()` and
a slice from its cache. Anything else goes back to the database, once per
parent object, with the prefetch query already paid for on top:
orders = Order.objects.prefetch_related("lines")
for order in orders:
for line in order.lines.filter(active=True): # one query per order
That costs more than never prefetching at all, and it reads like an
optimisation, which is why it survives review.
Reported only where the prefetch and the accessor are provably the same
object - bound in the same scope, or the loop variable iterating it.
`nplusone` finds the neighbouring problem, an eager load nothing touches,
at runtime; `unused_eager_loading` answers that one statically for DRF.
Args:
search_path: directory to scan. Defaults to the configured project.
include_tests: also report inside test files.
| Name | Required | Description | Default |
|---|---|---|---|
| search_path | No | ||
| include_tests | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and destructiveHint=false, and the description does not contradict them. The description adds valuable context about the tool's behavior: it is static analysis, it only reports when the prefetch and accessor are provably the same object (conservative), and it does not execute code. It also mentions the tool is scoped to a directory search_path registry. However, it doesn't detail output schema or performance characteristics, but that is acceptable given the annotations and output schema presence.
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 thorough but somewhat long; it includes a code example and a paragraph distinguishing from sibling tools. The purpose is front-loaded, and the parameters are summarized. It is appropriately structured but could be tightened; the code example, while helpful, adds length. A score of 4 reflects that every sentence earns its place, but it is longer than strictly necessary.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool is a static analyzer with an output schema (not shown but present), the description sufficiently explains the purpose, usage, scope, and parameters. It covers behavior, limitations (provably same object), and distinguishes from neighboring tools. The output schema likely describes return structure, so the description doesn't need to detail that. It is complete for an agent to decide when to use and what parameters to pass.
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 input schema describes `search_path` as a string with default null and `include_tests` as a boolean. The description elaborates on what these parameters do: 'directory to scan' and 'also report inside test files', which goes beyond the schema's minimal titles. However, with 0% schema description coverage, the description carries the full burden for parameter meaning; it does a decent job but could be more explicit about how `search_path` is resolved when null (defaults to project). Overall, it adds value but not full 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 clearly identifies this as a static analysis tool that reports 'defeated prefetches' – specific inefficient query patterns in Django ORM code. It uses specific verb ('reports') and a precise resource ('relations that were prefetched and then re-queried' builds on the tool's name but adds concrete meaning). It distinguishes itself from sibling tools like `sqlalchemy_nplusone` and `unused_eager_loading`, explicitly noting differences.
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 includes a code example that illustrates the exact scenario, making it clear when this tool is appropriate. It explicitly contrasts with `nplusone` (runtime) and `unused_eager_loading` (static, for DRF), providing clear alternatives and conditions. The description also lists parameters and their defaults, implying when to use them (e.g., `include_tests`).
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
delete_impactARead-onlyIdempotent
Show what deleting one row of a model would take with it.
Follows on_delete across the whole model graph: which models lose rows
through CASCADE, which PROTECT relations would block the delete, and which
fields get set to NULL. Reads the graph only, never the database.
Args:
model_label: "app_label.ModelName", e.g. "shop.Customer".
max_depth: how far to follow chained cascades.
| Name | Required | Description | Default |
|---|---|---|---|
| max_depth | No | ||
| model_label | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description goes beyond the readOnlyHint and idempotentHint annotations by explicitly stating that it only reads the graph and never touches the database. It also discloses the specific behavior of following on_delete relations and how PROTECT relations can block deletion, which is valuable context for an agent deciding whether this is a safe analysis step.
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 well-structured: the purpose is stated in the first sentence, followed by concise explanatory detail and a clear Args section. Every sentence earns its place and there is no redundant or filler 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?
The description is complete for the tool's complexity. It covers both parameters with format and semantics, explains the tool's behavior, declares its read-only nature, and the presence of an output schema means return-value details are not required. An agent has all necessary information to invoke it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With schema description coverage at 0%, the description carries the full burden of explaining parameters. It does so effectively by giving the exact model_label format ('app_label.ModelName') with an example, and by describing max_depth as controlling how far chained cascades are followed.
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: it shows what deleting one row of a model would take with it, and clarifies that it follows on_delete relationships across the model graph. This makes its purpose distinct from generic model inspection or migration tools and clearly positions it as a delete-impact analysis 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?
The description provides clear context for when to use the tool: when assessing the cascading consequences of deleting a model row. It explains what the tool covers (CASCADE, PROTECT, SET_NULL) but does not explicitly name alternative sibling tools 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.
deploy_safetyARead-onlyIdempotent
Is a pending destructive migration safe to deploy yet?
A migration linter says RemoveField is backward incompatible, always. This
answers the question that actually decides the deploy: has the code caught
up? For every unapplied migration that removes or renames a field, model,
index or constraint, the source tree is searched for code that still refers
to it, and each one comes back either "blocking" with file and line numbers,
or "clear".
Args:
search_path: directory to scan. Defaults to the configured project path.
max_hits_per_symbol: stop after this many references per symbol.
| Name | Required | Description | Default |
|---|---|---|---|
| search_path | No | ||
| max_hits_per_symbol | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The annotations already mark the tool as read-only and idempotent, and the description adds what actually happens: for every unapplied destructive migration, the source tree is searched and each reference is reported as 'blocking' with file/line details or 'clear'. It also clarifies that a null search_path effectively defaults to the configured project path. No contradiction exists between description and annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is moderately sized and front-loaded with the core question, then the value proposition, then parameter docs. The prose about the migration linter adds context and earns its place, but it could be tightened without losing meaning.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the simple two-optional-parameter schema, the annotations, and the existing output schema, the description covers the decision context, scan scope, and result categories. It does not discuss edge cases like no pending migrations or performance implications, but these are not essential 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?
With schema description coverage at 0%, the description fully compensates by explaining both parameters: search_path is the directory to scan with a project-path default, and max_hits_per_symbol bounds how many references are checked per symbol. This gives meaning to otherwise bare schema properties, though 'symbol' could be more explicitly defined.
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 decision question and mechanism: it checks whether pending destructive migrations are safe by scanning the source tree for code references to removed/renamed fields, models, indexes, or constraints. This clearly distinguishes it from a generic migration linter by focusing on code readiness. The verb ('search'), resource ('source tree'), and outcome ('blocking'/'clear') are concrete.
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 opening question 'Is a pending destructive migration safe to deploy yet?' plus the contrast with a migration linter that always flags RemoveField tells the user when this tool is the right choice. It does not explicitly name sibling alternatives like migration_risk or list exclusion conditions, but the intended context is clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
endpoint_costARead-onlyIdempotent
How many queries one request to each endpoint will cost.
Every tool that answers this runs the application and tells you afterwards:
the debug toolbar, silk, assertNumQueries. The number is derivable before
anything runs. One query for the page, plus one per object for every
serializer field crossing a relation the view did not prefetch, plus that
again per level of nesting.
On the demo project the same serializer measured 2852 queries behind an
unoptimised queryset and 2 behind an optimised one. The ratio is the
reliable part; the absolute number is only as good as nested_fan_out.
Args:
page_size: objects a list response returns.
nested_fan_out: assumed children per parent one level down. A property
of your data that reading the code cannot reveal.
list_only: skip views that only ever return a single object.
| Name | Required | Description | Default |
|---|---|---|---|
| list_only | No | ||
| page_size | No | ||
| nested_fan_out | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already mark it read-only and idempotent, and the description adds substantial behavioral context: the estimation formula, dependency on nested_fan_out, and the caveat that the ratio is reliable while absolute numbers are only as good as the assumption. This gives the agent a clear picture of accuracy and limitations.
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, and every paragraph earns its place: alternative tools, static derivability, the estimation model, a compact calibration example, and parameter docs. The example is illustrative rather than padding.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 3-parameter estimation tool with an output schema, the description covers what it computes, how it computes it, parameter meanings, and limitations. The output schema handles return-value details, so no critical 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 description coverage is 0%, but the Args section fully documents all three parameters with meaningful semantics: page_size as list response size, nested_fan_out as an external data property, and list_only as a filter for single-object views. This fully compensates for 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?
The description states a precise metric (query count per request) and resource (each endpoint), and makes clear this is a static, pre-execution estimate. It distinguishes itself from runtime-measurement tools like the debug toolbar, silk, and assertNumQueries.
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 explicitly contrasts with tools that answer the same question by running the application, implying this tool is for when a pre-execution estimate is wanted. It stops short of enumerating sibling analysis tools or giving an explicit when-not-to-use list.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
escaping_side_effectsARead-onlyIdempotent
Calls inside a transaction whose effect cannot be rolled back.
A transaction can be rolled back. An email cannot, and neither can a
webhook or a task a worker has already picked up.
with transaction.atomic():
order = Order.objects.create(...)
send_confirmation.delay(order.pk)
Two defects, and only one is famous. The race: the broker has the task
immediately, a worker can start before the commit, and it queries for a row
that is not there. It passes every test, because tests run in a transaction
that never commits with a worker that runs eagerly, and it fails under load.
The quieter one: if anything after that line raises, the order is gone and
the customer has the email.
The fix is transaction.on_commit, and calls already deferred that way are
not reported. The ecosystem's answer to this is runtime wrappers; ruff and
flake8-django do not look at it.
Args:
search_path: directory to scan. Defaults to the project root.
include_low_confidence: also report calls like `.send()` that are
guessed from the name, since it is also Signal.send and socket.send.
| Name | Required | Description | Default |
|---|---|---|---|
| search_path | No | ||
| include_low_confidence | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the readOnly/idempotent/destructive annotations, the description discloses detection behavior in detail: it scans a search path, it guesses low-confidence `.send()` calls due to ambiguity with Signal.send and socket.send, and it excludes already-deferred on_commit calls. It also explains why false negatives occur in tests and why this fails under load, giving the agent an accurate model of what the tool reports and why.
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 definition, followed by a well-structured explanation and a clear Args section. The code example and the narrative about the two defects add valuable context but make the text longer than strictly necessary. Every sentence contributes to understanding scanning behavior and false-positive risk, though a more concise wording could tighten it without losing meaning.
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 two optional parameters, an output schema, and a non-trivial detection domain. The description covers what it detects, how it scans, what it excludes, parameter defaults, and the ambiguity of low-confidence reports. With the output schema provided separately, no critical information appears missing for an agent to decide whether and how to invoke it.
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 full responsibility for parameter meaning. The 'Args:' section documents both parameters: search_path (directory to scan, default project root) and include_low_confidence (whether to include guessed `.send()` calls, with rationale about Signal.send and socket.send). This adds significant semantic value beyond the bare schema, including defaults and ambiguous cases.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a precise, specific definition: 'Calls inside a transaction whose effect cannot be rolled back.' It then elaborates with a concrete Django/Celery example and explains that it reports such calls while excluding those already deferred via transaction.on_commit. This clearly distinguishes it from siblings like race_conditions or bypassed_effects by focusing on rollback-escaping side effects.
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 provides strong contextual guidance: it explains the two defect types (race and rollback failure), notes that already-deferred on_commit calls are not reported, and states that ruff and flake8-django do not cover this issue, implying this tool fills that gap. However, it does not explicitly name sibling tools or contrast itself with them, stopping short of the explicit when-to-use-vs-alternatives guidance of a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
explain_modelARead-onlyIdempotent
Everything known about one model, and the risks only visible combined.
Start here when meeting a model for the first time. It runs the structural,
ownership, deletion, signal, exposure, index and datetime checks and returns
one picture instead of seven reports.
The part worth reading is `correlated_risks`. Some defects exist only in the
overlap and no single analyser can see them: a model that is owned, read
without scoping, and serialised with fields = "__all__" is a complete path
from a URL to another customer's row, while each of those three alone is
just a warning.
Args:
model_label: "app_label.ModelName".
tenant_root: the model that owns data, for the ownership half.
include_raw: attach the full report from each analyser as well.
| Name | Required | Description | Default |
|---|---|---|---|
| include_raw | No | ||
| model_label | Yes | ||
| tenant_root | No | auth.User |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already establish read-only, idempotent, non-destructive behavior. The description adds meaningful behavioral context beyond that: it runs multiple analysis passes, returns a combined picture, and highlights correlated_risks as the key output. It also gives a concrete example of an interlocking defect, which helps the agent understand what the tool actually reveals.
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 well-structured with a clear opening, usage context, behavioral explanation, and a compact args list. The correlated_risks example is valuable but slightly verbose; still, every part contributes to correct understanding and invocation.
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 read-only analysis tool with an output schema already present, this description is complete: it says what the tool does, when to start with it, why its output matters, and exactly what each parameter means. No critical information needed for selecting and invoking the tool is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description carries the full burden of explaining parameters. It does this well: model_label is given with format 'app_label.ModelName', tenant_root is explained as the owning model for the ownership half, and include_raw is described as attaching each analyser's full report. This goes beyond the raw schema types and defaults.
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 gives a specific purpose: aggregate all model checks into one picture, with correlated risks highlighted. It clearly distinguishes itself from the many single-purpose sibling tools by saying it runs structural, ownership, deletion, signal, exposure, index, and datetime checks instead of seven separate reports.
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 explicitly says 'Start here when meeting a model for the first time,' which is strong usage guidance. It implies the alternative is running individual analysis tools, but it does not name those siblings explicitly or state when NOT to use them.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
fastapi_exposureARead-onlyIdempotent
FastAPI endpoints that serialise more than they declare.
@app.get("/users/{pk}")
async def get_user(pk: int):
return session.get(User, pk)
No response_model and no return annotation, so FastAPI serialises whatever
it is handed - the whole ORM object, every column, including the ones
added to the model next month. The absence of one line is the entire bug,
so there is nothing in the file to read or review.
Every FastAPI guide says to set response_model and several say a CI rule
should enforce it. No linter ships one.
An endpoint returning a dict or a literal is not reported: the author
decided what goes in it. Unauthenticated is critical, behind a dependency
is high - it still leaks to everyone who can log in.
Nothing here imports the project, because a FastAPI app usually wants a
database URL and a secret before it will import at all, and none of that is
needed to read a decorator. Needs no Django.
Args:
search_path: directory to scan. Defaults to the configured project.
| Name | Required | Description | Default |
|---|---|---|---|
| search_path | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description adds substantial behavioral detail beyond the read-only/idempotent annotations: it does not import the project, requires no database URL or secret, needs no Django, and only scans decorators for missing response_model/return annotations. It also discloses the security consequence of the leak. This gives an agent a clear and accurate model of how the tool behaves.
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 longer than average but well modularized: example, detection rule, false-positive scope, severity model, runtime constraints, and args. The core idea is front-loaded, and each paragraph earns its place. It is slightly verbose and repeats the missing-annotation concept, so it is not maximally concise.
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 static-analysis tool with one optional parameter and an output schema, the description is complete: it explains what is detected, how detection works, known false positives, severity levels, runtime constraints, and the search_path argument. The output schema covers return values, so their omission is acceptable. The 'Needs no Django' note also helps distinguish it from Django-specific sibling tools.
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 schema provides only the parameter title 'Search Path' and a null default, so description coverage is 0%. The description compensates with 'search_path: directory to scan. Defaults to the configured project,' which defines both the parameter's meaning and its default behavior. It does not explain what 'configured project' resolves to, which keeps it from a 5.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The opening sentence names the resource and bug clearly: FastAPI endpoints that serialise more than they declare. The example and the explanation about missing response_model/return annotations make the tool's purpose concrete. It stops short of 5 because it uses a descriptive noun phrase rather than an explicit verb like 'detect', and it does not explicitly name a sibling tool for contrast.
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 practical usage context: it positions the tool as the CI rule that no linter ships, and it provides severity guidance ('Unauthenticated is critical, behind a dependency is high'). It also states an explicit exclusion: endpoints returning a dict or literal are not reported. It does not explicitly say when to prefer a sibling tool, though 'Needs no Django' hints at the Django-oriented alternatives.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
find_n_plus_oneARead-onlyIdempotent
Find relation traversals in a template that each cost a query.
Resolves attribute chains against the real model graph and flags the ones
that cross a relation inside a loop, which is where N+1 queries come from.
Reports candidates: whether a crossing really costs a query depends on the
queryset in the view, which this does not read.
Args:
template_path: path to the template file.
root_models: context variable to model label, e.g.
{"orders": "shop.Order"}. Loop variables inherit from these.
| Name | Required | Description | Default |
|---|---|---|---|
| root_models | Yes | ||
| template_path | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description goes beyond the readOnly/idempotent annotations by explaining that results are candidates, not confirmed costs, and that queryset context is intentionally ignored. It also describes the resolution mechanism (attribute chains against the real model graph) and the loop condition. This appropriately frames the tool's limitations.
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 starts with a one-line purpose, then explains method and limitation, then documents args. Each sentence adds a distinct fact and there is no boilerplate. The only minor issue is that 'that each cost a query' in the first sentence overstates what is later correctly labeled as a candidate.
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 two-parameter, read-only analyzer with an output schema, the description covers what the tool scans, how it resolves models, its main limitation, and how to pass inputs. It does not need to document return values because an output schema exists. The description is complete enough to select and invoke the tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0%, so the Args block carries the descriptive burden. Both parameters are explained: template_path is a path to the template, and root_models is a context-variable-to-model-label mapping with an example and a note on loop-variable inheritance. This is sufficient to construct a valid call, though root_models semantics could be expanded slightly.
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 names a concrete resource ('relation traversals in a template') and a specific diagnostic action ('Find... flags the ones that cross a relation inside a loop'). It is clearly template-scoped and distinct from sibling tools focused on ORM, serializer, or query paths. There is no ambiguity about what the tool analyzes.
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 states a clear context: it scans templates for candidate N+1 traversal patterns and explicitly warns that whether it actually costs a query depends on the view queryset, which the tool does not read. This tells an agent when not to treat results as definitive, but it does not name alternative sibling tools for the view/ORM side, so guidance is clear but not fully explicit.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
find_unscoped_queriesARead-onlyIdempotent
Find querysets that read tenant-scoped data without scoping the query.
This is the shape behind most IDOR reports: a view loads an object by
primary key and never checks who owns it. Generic analysers struggle
because the defect is the absence of a filter, and absence has no syntax.
The model graph makes it tractable: it knows Order reaches the tenant root
through 'customer', so it can tell that filtering on pk alone is not enough.
Candidates, not verdicts. A filter in a base class, a mixin, a custom
manager or a get_queryset() override is invisible from here.
Args:
tenant_root: the model that owns data, e.g. "auth.User" or "shop.Customer".
search_path: directory to scan. Defaults to the project path.
max_depth: how many relation hops still count as owned.
include_exempt: also scan admin, management commands and tests.
| Name | Required | Description | Default |
|---|---|---|---|
| max_depth | No | ||
| search_path | No | ||
| tenant_root | No | auth.User | |
| include_exempt | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly, idempotent, and non-destructive behavior. The description adds substantial behavioral nuance beyond that: it warns that results are 'Candidates, not verdicts' and explicitly lists invisible sources of filters such as base classes, mixins, custom managers, and get_queryset() overrides. This helps an agent interpret results correctly.
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 purpose, then provides essential reasoning and limitations, and closes with a compact parameter list. Every section earns its place; there is no padding or repetition of schema/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?
Given an output schema exists, the return format does not need to be spelled out here. The description covers what the tool does, why it is valuable, what it cannot detect, and what each argument means, making it complete for correct invocation and result interpretation.
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%, yet the description compensates fully by explaining every parameter with concrete meaning: tenant_root is the owning model with examples, search_path is the scan directory with default, max_depth defines relation-hop ownership limits, and include_exempt specifies which extra code areas to scan. This is exactly the semantic enrichment an agent needs.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Find querysets that read tenant-scoped data without scoping the query.' It further distinguishes itself by explaining this is the shape behind most IDOR reports and why generic analyzers struggle, making the tool's niche clear relative to sibling tools.
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 provides clear context for when this tool is appropriate: hunting IDOR-style defects where a view loads an object by primary key without ownership checking. It does not explicitly name sibling tools or state when not to use it, but it gives enough situational guidance for an agent to select it.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_modelsARead-onlyIdempotent
List the project's models with their fields and relations.
Args:
app_label: Restrict to one app, e.g. "shop". Omit for all apps.
include_fields: Set False for a short overview without field details.
| Name | Required | Description | Default |
|---|---|---|---|
| app_label | No | ||
| include_fields | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
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 the safety profile is well covered. The description adds useful context about output scope—fields, relations, and optional short overview—but does not disclose additional behavioral traits like pagination, ordering, or performance characteristics.
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 core purpose. The Args section is clearly structured and each sentence earns its place without unnecessary elaboration.
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 read-only listing tool with an output schema and annotations covering safety, this description is complete. It documents both optional parameters, states the resource scope, and needs no additional return-value detail because the output schema exists.
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 fully compensates. It explains both parameters with concrete semantics and an example: app_label restricts to a single app, and include_fields toggles field-level detail. This goes well beyond the parameter names in the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb and resource: 'List the project's models with their fields and relations.' This clearly distinguishes it from sibling analysis tools like explain_model or find_n_plus_one by stating exactly what this tool returns.
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 Args section provides clear guidance on how to customize the call: restrict to one app via app_label, omit for all apps, and set include_fields to False for a short overview. It does not explicitly name alternative tools or state when not to use it, but the usage context is clear enough for this simple listing tool.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
migration_riskARead-onlyIdempotent
Rate migrations by what they do to a live database.
Flags operations that block writes, rewrite a table, or break the code that
is still running during a rolling deploy.
Args:
include_applied: also classify migrations that already ran.
| Name | Required | Description | Default |
|---|---|---|---|
| include_applied | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already establish readOnlyHint=true, idempotentHint=true, and destructiveHint=false. The description adds useful analytic context about what it flags and that include_applied can extend classification to already-run migrations. There is no contradiction with the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact and front-loaded: first the general purpose, then the specific risk signals, then the argument explanation. Every sentence earns its place, and the formatting is easy to scan.
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 one optional parameter, no required arguments, clear annotations, and an output schema present, the description covers everything needed to select and invoke the tool. The behavior is sufficiently described, and the output schema handles return-value details.
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 schema only exposes a boolean 'include_applied' with a default, and schema description coverage is 0%. The description compensates by explaining that include_applied means 'also classify migrations that already ran,' which gives the agent the key semantic needed to use the parameter correctly.
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 action ('Rate migrations') and resource ('a live database'), then adds concrete criteria by listing dangerous operations: blocking writes, rewriting a table, or breaking running code during a rolling deploy. It is clear, though it does not explicitly differentiate itself from sibling tools like deploy_safety.
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 implies usage: use this when you need to evaluate the risk of database migrations against a live system, especially around write availability and rolling deploys. It does not explicitly describe when not to use it or compare it with alternatives such as deploy_safety, but the intended context is clear enough.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
missing_indexesARead-onlyIdempotent
Fields the code filters or sorts on that carry no index.
Runtime tools answer this by watching real traffic, which only ever covers
the paths traffic reached. Reading the source covers every path in the
repository, works with no database and no traffic, and can run on a branch
before it ships.
The trade is that it cannot weigh anything: a filter on a forty row table
looks like one on a forty million row table. It reports where an index is
missing and how often the code asks for it, and leaves the decision to
somebody who knows the row counts.
Args:
search_path: directory to scan. Defaults to the project path.
min_occurrences: only report a field asked for at least this often.
| Name | Required | Description | Default |
|---|---|---|---|
| search_path | No | ||
| min_occurrences | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already mark the tool read-only and idempotent; the description adds valuable behavioral context: it statically reads source, needs no database/traffic, reports how often a field is queried, and deliberately leaves weighting decisions to the user. No contradictions with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is longer than average but every sentence carries meaning: the definition, the contrast with runtime tools, the limitation, and parameter docs. The core purpose is front-loaded, though the runtime-tools paragraph could be slightly tighter.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema provided, annotations, a complete parameter explanation, and a clear behavioral model including limitations, an agent has enough context to invoke this tool correctly and interpret its results. Nothing essential is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema has no descriptions for the parameters, but the description compensates fully: search_path is documented as the directory to scan with a project-path default, and min_occurrences is documented as the frequency threshold for reporting. This gives an agent everything needed to set both.
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, 'Fields the code filters or sorts on that carry no index,' states exactly what the tool returns and ties directly to the tool name. The rest of the description clarifies it reports missing indexes from source code, distinguishing it from runtime-based tools.
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 explicitly contrasts runtime tools with this source-based approach: it works with no database and no traffic, can run on a branch before it ships, and covers every path. It also names the key trade-off (cannot weigh importance) so an agent knows when to prefer or avoid this tool.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
money_precisionARead-onlyIdempotent
Places where a decimal amount stops being exact.
A DecimalField exists so that money is exact. Four things give that up,
and they are not equally bad:
Decimal(0.1) wrong from birth - 0.1 has no exact binary
form, so this is 0.1000000000000000055...
float(invoice.amount) a one-way door; everything after is approximate
round(amount, 2) exact, but banker's rounding: 0.125 becomes
0.12 where an invoice expects 0.13
FloatField("price") the column itself cannot hold money
Decimal(0.5) is NOT reported as a defect: that float is exactly
representable and nothing is lost. The check computes the round trip, so
on a real project 41 of 50 Decimal(<float>) calls came back harmless and
11 were genuinely wrong. Nothing in the linter ecosystem looks at this;
the usual advice stops at the model definition and every one of these
happens somewhere else.
Args:
search_path: directory to scan. Defaults to the project root.
| Name | Required | Description | Default |
|---|---|---|---|
| search_path | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the readOnly/idempotent/non-destructive annotations, the description explains exact detection semantics: four defect categories, the explicit exclusion of Decimal(0.5), the round-trip verification approach, and real-world false-positive rates. This gives the agent a precise model of what the tool will flag and what it will ignore.
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 idea, uses a scannable bullet list for the four failure modes, and every paragraph adds either detection detail, a false-positive rule, or project context. The length is justified by the nuanced subject matter.
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 audit tool with an output schema, the description covers what is checked, what is deliberately not reported, how the check behaves, and how to point it at a directory. Nothing essential is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With 0% schema description coverage, the description must carry parameter meaning, and it does: search_path is defined as the directory to scan with a default of the project root. It doesn't spell out path format or edge cases, but for a single optional parameter this is adequate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a crisp thesis—'Places where a decimal amount stops being exact'—and then enumerates the four concrete code patterns that trigger the check, making the tool's function evident. It doesn't use an explicit verb like 'scan' or 'report', but the domain and behavior are unmistakable from the examples and 'reported as a defect'.
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 text gives clear context about when the tool adds value: it covers precision loss that happens outside the model definition, where 'the usual advice stops' and where 'nothing in the linter ecosystem looks'. It does not name sibling tools or state explicit when-not-to-use conditions, but the context is strong enough for an agent to know this is the money-precision audit.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
multiplied_aggregatesARead-onlyIdempotent
Aggregates whose numbers are wrong because a join multiplied the rows.
Order.objects.annotate(lines=Count("lines"), shipments=Count("shipments"))
Joining two multi-valued relations gives the cartesian product of them: an
order with 3 lines and 2 shipments produces 6 rows, and both counts come
back as 6. Nothing raises. Two plausible numbers, both the product of the
two, usually on a dashboard nobody can check by hand.
Only Count and Sum are reported. A join repeats rows uniformly within each
group, so Min and Max return the value they would anyway and Avg divides a
multiplied total by a multiplied count - including them reported a correct
query as a defect on the first real project this saw.
Count(distinct=True) is treated as correct. Sum has no equivalent and needs
a Subquery, so a query is still reported when every Count in it is distinct
but a Sum crosses a second relation.
Django's own documentation warns about this and no linter checks it.
Args:
search_path: directory to scan. Defaults to the configured project.
| Name | Required | Description | Default |
|---|---|---|---|
| search_path | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already mark the tool as read-only, idempotent, and non-destructive. The description goes well beyond that by explaining what gets reported, what does not, and why edge cases like Min, Max, Avg, and distinct counts are handled the way they are. This gives an agent a precise mental model of the tool's behavior.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is longer than average, but every paragraph earns its place: it explains the core problem, the reporting scope, edge-case rationale, and external context. The information is well-organized and front-loaded with the central concept before diving into specifics.
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 analysis rule with a single parameter and an output schema, the description is essentially complete. It covers the defect being detected, the exact aggregate functions considered, the reasoning behind exclusions, and the parameter behavior. No critical operational detail is missing for an agent to select and invoke the 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?
The schema has 0% description coverage, so the description must carry the weight for the single search_path parameter. It does: 'directory to scan. Defaults to the configured project' adds meaning beyond the raw schema field name, though it could provide more detail about path resolution or validity.
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 clearly identifies the tool's purpose: reporting aggregates corrupted by join multiplication, with a concrete Django ORM example. It distinguishes itself from the many sibling analysis tools by specifying exactly which aggregate expressions are in scope (Count and Sum) and which are not.
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 explains when the tool is relevant and gives detailed coverage rules: only Count and Sum are reported, Count(distinct=True) is treated as correct, and Min/Max/Avg are intentionally excluded. It does not explicitly name sibling alternatives or state 'use this when...', but the detection scope is clear and actionable.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
open_endpointsARead-onlyIdempotent
Endpoints anyone can call, crossed with what their serializer exposes.
serializer_exposure knows CustomerExportSerializer leaks a password reset
token; a Semgrep rule knows a view has AllowAny. Each alone is a judgement
call - maybe the serializer only feeds an admin export, maybe the view
serves a catalogue. Together there is nothing left to judge, and neither
check can make the connection alone.
DRF's own default permission is AllowAny. A project that never configured
DEFAULT_PERMISSION_CLASSES has every view without explicit
permission_classes open, and none of them say so; that is volunteered
first. Views overriding get_permissions() are listed, not judged.
Args:
include_unbounded: also report open endpoints whose serializer uses
fields="__all__" or exclude, even with nothing sensitive on the
model today. The next migration decides what leaks.
| Name | Required | Description | Default |
|---|---|---|---|
| include_unbounded | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already mark the tool as read-only and idempotent, and the description adds meaningful behavioral detail: it voluntarily surfaces default AllowAny views, lists but does not judge get_permissions() overrides, and explains how include_unbounded handles unbounded serializers.
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 and the argument semantics are clearly separated, but the middle narrative about judgement calls is somewhat longer than necessary. Still, it earns its place by justifying the tool's existence and behavior.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With only one optional parameter, an output schema present, and annotations covering safety, the description covers all essential context: what is reported, what is deliberately not judged, when to use the flag, and why the tool matters.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description carries the full burden for include_unbounded. It explains exactly what the flag does, including the fields='__all__' or exclude condition and the reason it matters for future migrations.
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 names a concrete resource ('endpoints anyone can call') and the specific analytical lens ('crossed with what their serializer exposes'). It also distinguishes the tool from the standalone serializer_exposure and Semgrep AllowAny checks, making the unique value obvious.
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 explains why this tool is needed when either signal alone is inconclusive, and it highlights DRF's AllowAny default as a critical context for when the tool is useful. It stops short of explicitly naming sibling alternatives or stating 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.
project_infoARead-onlyIdempotent
Check that the target Django project loads, and report what it is.
Run this first when something is not working. It is the smallest call that
proves both halves of the setup: the MCP transport and the Django boot.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare the tool read-only, idempotent, and non-destructive. The description adds valuable behavioral context beyond those annotations by explaining what the call proves about the environment (MCP transport and Django boot), which is exactly the kind of context an agent needs for a first-step diagnostic. No contradiction with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a compact two-sentence definition with the primary purpose front-loaded. The second sentence earns its place by giving usage context and explaining why this tool is the correct first call. There is no redundant or filler language.
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 zero-parameter, read-only health-check tool, the description covers what the tool does, when to run it, and what it proves about the setup. The presence of an output schema means return-value details do not need to be spelled out in the description, and annotations cover the behavioral safety profile.
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?
This tool has zero parameters, so the baseline is 4. The description does not need to explain parameter behavior, and schema coverage is effectively complete with an empty input 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?
The description states a specific verb ('Check that the target Django project loads') and a clear resource (the Django project), making the tool's purpose immediately understandable. It does not explicitly distinguish itself from siblings like 'check' or 'project_profile', but the 'report what it is' phrasing and emphasis on setup verification make the identity reasonably clear.
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 explicit usage timing: 'Run this first when something is not working.' It also explains why it should be run first, because it is the smallest call proving both MCP transport and Django boot. It does not name alternatives or state when not to use this tool, but the guidance is clear and actionable.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
project_profileARead-onlyIdempotent
What this project is built on, without needing Django to boot.
Frameworks are counted by how many of the project's own files import
them, not by what is installed: a package sitting in the virtualenv that
nothing imports is a fact about the environment, not the code. A project
can be Django and FastAPI at once and both are reported.
Use it to find out which checks can say anything here.
Args:
search_path: directory to scan. Defaults to the configured project.
| Name | Required | Description | Default |
|---|---|---|---|
| search_path | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Behavior: Reasoning -- The description adds meaningful behavior beyond annotations: it avoids Django boot overhead, counts imports from the project's own files rather than installed packages, and can report multiple frameworks at once. Annotations already indicate read-only, idempotent, and non-destructive behavior; the description enriches this with methodology and runtime expectations.
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 purpose, followed by the important counting methodology, and ends with a usage pointer. The Args section is compact and every sentence adds distinct value without redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the single optional parameter, the presence of an output schema, and strong annotations, the description covers purpose, when to use, parameter behavior, and key edge cases. There is no meaningful missing context for an agent to invoke it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0%, so the description must compensate. It defines search_path as a directory to scan and states the default is the configured project, adding semantic meaning beyond the raw schema properties.
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 clearly states the tool's purpose: identifying what frameworks a project is built on, without needing Django to boot. It further distinguishes itself by explaining that frameworks are counted by project file imports, not installed packages, and that multiple frameworks can be reported simultaneously.
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 explicitly says 'Use it to find out which checks can say anything here,' giving a clear when-to-use context before running analysis checks. It does not explicitly name alternatives or state when not to use it, but the guidance is strong enough for an agent to select the tool appropriately.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
queries_in_loopsARead-onlyIdempotent
Database work written inside a loop, split by what the fix is.
The template and serializer checks here find the N+1 a framework causes.
This finds the one somebody wrote by hand, which is where it lives in a
codebase whose views build their responses themselves.
Three shapes share one appearance and need three different fixes:
Customer.objects.get(pk=order.customer_id) uses the loop variable:
once per row, needs a bulk
fetch or a prefetch
Config.objects.get(key="vat") does not: the same
question N times for the
same answer, move it above
the loop
order.save() N round trips; bulk_update
fixes it and skips signals
django-check does static N+1 for relation access in a loop and is the
closest existing tool; nplusone and the debug toolbar find it at runtime.
The separation is what is added here.
Args:
search_path: directory to scan. Defaults to the configured project.
include_writes: also report save()/delete() inside a loop.
| Name | Required | Description | Default |
|---|---|---|---|
| search_path | No | ||
| include_writes | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate a read-only, idempotent, non-destructive operation, so the description doesn't need to restate safety. It adds useful behavioral detail about the three code shapes it detects, the three different fixes, and how include_writes extends reporting to save()/delete() calls.
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 purpose and then expands with concrete code examples and routing guidance. The three-shape example block earns its place by clarifying what counts as a loop query, and the Args section is clean and minimal.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the output schema exists and annotations cover safety, the description is largely complete: it explains the pattern detected, the categories of fixes, the alternative tools, and the parameters. A small gap is that it never maps the mentioned template/serializer checks to specific sibling names, though the context makes this recoverable.
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 parameter descriptions in the Args section carry the weight. They explain search_path as a directory with a default of the configured project and describe include_writes' effect on reporting writes in loops. This is enough for an agent to understand both parameters, though it remains brief.
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 the tool finds hand-written database work inside loops and splits it by the fix required, which is a specific behavior rather than a restatement of the name. It also distinguishes this tool from framework-caused N+1 checks in templates and serializers, helping differentiate it from nearby 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?
The description explicitly says this tool is for hand-written loop queries, while template/serializer checks cover framework-caused N+1, django-check covers static relation access, and nplusone/debug toolbar target runtime detection. This gives clear when-to-use and when-not-to-use guidance with named alternatives.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
race_conditionsARead-onlyIdempotent
Read-modify-save races, and row locks taken outside any transaction.
product = Product.objects.get(pk=pk)
product.stock -= quantity
product.save()
Two requests read 10, both subtract 3, both write 7; one sale is gone. A
transaction does not help, since neither sees the other's uncommitted
write. The fix is F("stock") - quantity so the database does the maths,
or select_for_update() inside atomic() to hold the row - and both of
those are silent here. Counters, balances, stock, retry counts: the
fields where off-by-one costs money.
Also: get_or_create() on a lookup no unique field, unique_together or
UniqueConstraint covers - two requests miss the get together, both
create, and the next call raises MultipleObjectsReturned. And
select_for_update() with no atomic() around it, which is not a race
but a TransactionManagementError the first time the line is reached.
Whether a transaction is open is judged with the call graph, so a caller's
atomic(), a decorator and ATOMIC_REQUESTS on a view all count.
Args:
search_path: directory to scan. Defaults to the project root.
include_parameters: also report mutations of an instance passed in
as a parameter, at medium confidence (the caller may hold a lock).
| Name | Required | Description | Default |
|---|---|---|---|
| search_path | No | ||
| include_parameters | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already signal read-only, idempotent, and non-destructive behavior, and the description adds substantial beyond-schema context: that correct fixes are 'silent', that whether a transaction is open is judged via the call graph, and that get_or_create misuse can raise MultipleObjectsReturned. This richly discloses behavior without contradicting 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?
Although lengthy, the description is dense and well-structured: it front-loads the core race pattern, uses a concrete code example, then systematically covers additional edge cases, and ends with parameter docs. Every sentence adds meaningful guidance; there is 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?
Given the presence of an output schema, the description does not need to describe return values. It fully covers scan scope, parameter behavior, transaction-context inference, and the specific Django patterns reported, making it complete for an agent to decide whether and how to invoke the 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 carries the full burden, and it succeeds. It explains search_path's default and meaning, and it explains include_parameters' effect, including the medium-confidence reasoning about the caller possibly holding a lock.
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 clearly identifies the tool's domain: it reports read-modify-save races, row locks outside transactions, get_or_create races, and select_for_update misuse. It distinguishes itself from the sibling list by focusing on concurrency/race patterns, though it never uses an explicit verb like 'scan' or 'find' in the opening sentence, relying instead on a noun-phrase heading.
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 explains the inputs (search_path, include_parameters) and gives practical guidance about where the tool matters ('Counters, balances, stock, retry counts: the fields where off-by-one costs money'). It does not explicitly name alternative tools or state when not to use it, so it falls short of full when/when-not guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
request_impactARead-onlyIdempotent
Every finding, grouped by the entry points that actually reach it.
The other checks answer "where is this defect". A few hundred correct
entries sorted by severity still does not say where to start, because risk
is severity times how often the code runs and nothing in the list says
whether a line is on the path of an endpoint served ten thousand times an
hour or of a command last run in 2023.
This runs the checks, maps each finding to the function containing it, and
walks the call graph backwards to the HTTP routes, Celery tasks, signal
receivers and management commands that reach it. Each finding carries the
path taken to it.
`unattributed` means no entry point this can see reaches the finding. It
does not mean unreachable and it does not mean safe - a plain Django
function view carries no decorator and belongs to no view class.
Args:
search_path: directory to scan. Defaults to the configured project.
max_depth: how many callers to walk back through.
tenant_root: passed to the ownership check when this runs the checks.
| Name | Required | Description | Default |
|---|---|---|---|
| max_depth | No | ||
| search_path | No | ||
| tenant_root | No | auth.User |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
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 the safety profile is known. The description adds valuable behavioral context beyond annotations: it walks the call graph backwards, explains the meaning and limitations of 'unattributed', and notes that a plain Django function view can be a false negative. No contradiction with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is organized with a lead summary, a rationale paragraph, an algorithm explanation, an 'unattributed' clarification, and an Args section. It is somewhat long but every section earns its place by adding context needed to interpret results correctly. The main idea is front-loaded in the first line.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the complexity of walking a call graph and the presence of an output schema, the description covers the essential semantics: what the tool produces, how entry points are found, and how to interpret 'unattributed' results. It does not mention potential performance costs or prerequisites like a configured project, but the default search_path implies that. Overall, enough for an agent to invoke and understand output correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description carries the full burden for parameters. It has a dedicated Args section explaining each parameter: search_path (directory to scan), max_depth (how many callers to walk back), and tenant_root (passed to ownership check). While max_depth is brief, all three parameters receive functional meaning beyond the raw 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?
The description clearly states the tool's specific function: 'runs the checks, maps each finding to the function containing it, and walks the call graph backwards to the HTTP routes, Celery tasks, signal receivers and management commands that reach it.' It distinguishes itself from sibling checks by explicitly contrasting with 'other checks' that answer 'where is this defect', making it easy to select among the many sibling tools.
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 provides clear usage context by explaining that risk is 'severity times how often the code runs' and that the tool helps decide where to start fixing. It implicitly names 'other checks' as alternatives but does not list specific sibling tool names. This gives sufficient guidance for when to use this tool without leaving the agent guessing.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
scan_templatesARead-onlyIdempotent
Run the N+1 analysis over every template in a directory.
find_n_plus_one needs a context map per template. This resolves it instead
from class-based views that declare template_name together with model or
queryset, so a whole project can be scanned without typing anything.
Args:
template_root: template directory. Defaults to the project path.
project_root: where to look for views. Defaults to the project path.
root_models: context applied to every template, for names no view supplies.
| Name | Required | Description | Default |
|---|---|---|---|
| root_models | No | ||
| project_root | No | ||
| template_root | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already establish readOnly, idempotent, and non-destructive behavior. The description adds genuinely useful behavioral detail: it resolves context from class-based views declaring template_name with model/queryset, uses root_models as a fallback, and defaults both roots to the project path. This is enough context beyond what annotations provide.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is tight and front-loaded: the action appears in the first sentence, the key differentiator follows immediately, and the args list is compact with no filler. Every sentence adds necessary information for selecting or invoking the tool.
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 three optional parameters, clear defaults, an output schema, and annotations covering safety, the description provides everything an agent needs to invoke this tool correctly. It even explains the integration path from views to templates, making the batch behavior understandable.
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 for parameter documentation. It explains all three parameters clearly: template_root, project_root, and root_models, including their defaults and the purpose of root_models as a fallback context source.
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: 'Run the N+1 analysis over every template in a directory.' It openly distinguishes itself from find_n_plus_one by explaining that this tool resolves the context map automatically, so an agent can tell them apart immediately.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description makes the usage context clear by contrasting with find_n_plus_one: that tool needs a context map per template, while this one derives it from class-based views to scan a whole project without manual input. It does not explicitly list exclusions or when to prefer the alternative, but the intended batch-use case is strongly implied.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
serializer_exposureARead-onlyIdempotent
What each DRF ModelSerializer exposes, and what looks unintended.
`fields = "__all__"` is a decision made once and then re-made silently by
every migration after it. Add a token column to the model and the API starts
returning it, with no diff on the serializer for anyone to review.
Args:
include_safe: also list serializers with an explicit, clean field list.
| Name | Required | Description | Default |
|---|---|---|---|
| include_safe | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already mark it read-only, idempotent, and non-destructive, so the bar is lower. The description adds meaningful behavioral context: it explains what counts as 'unintended' (fields='__all__' silently exposing new columns) and that include_safe broadens the listing. No contradiction with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Decisively front-loaded with the purpose, then a concrete motivating example, then the single argument. Every sentence earns its place — no fluff, no adjactives, and the structure is easy to scan.
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, read-only analysis tool with an output schema, this is nearly complete: purpose, trigger scenario, and parameter semantics are all covered. The only gap is a precise statement of what the default (non-include_safe) output contains, which is left to inference.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must carry the meaning. The Args block clearly defines include_safe: 'also list serializers with an explicit, clean field list.' This goes beyond the bare boolean schema. It doesn't spell out the default output, though 'also' strongly implies it.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States specific resource (DRF ModelSerializer exposure) and intent (surface unintended fields). Mentions DRF explicitly, distinguishing from fastapi_exposure, and the fields='__all__' scenario shows what it detects. However, it lacks an explicit action verb like 'list' or 'report', and doesn't directly name sibling tools.
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 example about a token column silently appearing in the API implies when this tool is valuable — reviewing serializer exposure after model changes. But it doesn't explicitly say when to use it vs alternatives like serializer_nplusone or api_contract, and gives no exclusions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
serializer_nplusoneARead-onlyIdempotent
N+1 queries in DRF serializers, with the queryset fix for each.
find_n_plus_one answers this for templates. Most Django written today
renders JSON, and there the N+1 comes from a nested serializer field: a list
of a hundred orders runs a hundred extra queries per nested relation.
Follows nested serializers, so the lookup it suggests is the full path.
Args:
max_depth: how far to follow nested serializers.
| Name | Required | Description | Default |
|---|---|---|---|
| max_depth | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With readOnlyHint and idempotentHint already covering safety, the description adds useful behavior: it follows nested serializers and suggests the full lookup path in the queryset fix. It doesn't fully spell out the output shape, but an output schema exists and annotations already cover side-effect concerns.
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 lean and front-loaded: it opens with the core purpose, then gives sibling context, traversal behavior, and the single argument. The opening is a fragment rather than an explicit sentence, but every line earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description covers the analyzed context (nested DRF serializer fields), the rationale (JSON vs templates), the traversal behavior, and the one adjustable parameter. With safety annotations and an output schema present, no critical invocation context is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema only provides 'max_depth' with a type and default, so the description's 'how far to follow nested serializers' adds meaningful semantics. For a single optional parameter and 0% schema description coverage, this is sufficient compensation.
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 line scopes the tool to 'N+1 queries in DRF serializers' and says a queryset fix accompanies each finding, which clearly separates it from template-oriented find_n_plus_one. It is clear and specific, though it relies on an implied verb rather than an explicit 'detects' or 'finds' statement.
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 explicitly names find_n_plus_one as the tool for templates, and frames this tool as the JSON/DRF serializer case with 'Most Django written today renders JSON'. This gives an agent clear when-to-use and alternative routing for the most relevant sibling.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
sqlalchemy_nplusoneARead-onlyIdempotent
Relationships SQLAlchemy will load one row at a time.
orders = db.query(Order).all()
for order in orders:
print(order.customer.name) # one query per order
And the quieter FastAPI shape, where there is no loop to see:
@app.get("/orders", response_model=list[OrderOut])
def list_orders(db=Depends(get_db)):
return db.query(Order).all()
OrderOut declares `items`, so serialisation walks the relationship once
per row - after the endpoint has returned, which is why nothing in the
function body mentions it.
nplusone finds this at runtime by watching lazy loads happen, and
lazy="raise" turns it into an exception; both need the code path to run.
A relationship declared lazy="selectin", "joined" or "raise" is never
reported here, since the first two are already eager and the third is the
recommended fix.
Nothing is imported. Needs no Django.
Args:
search_path: directory to scan. Defaults to the configured project.
| Name | Required | Description | Default |
|---|---|---|---|
| search_path | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description adds meaningful behavior beyond the readOnly/idempotent annotations: it is a runtime observer that requires the code path to run, it does not import anything, it does not require Django, and it will not report already-eager or raise-configured relationships. There is no contradiction with the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but every major section earns its place: two illustrative code shapes, the runtime mechanism, the exclusions, the no-import/no-Django note, and the argument definition. The core idea is front-loaded with the first sentence, and the examples clarify a non-obvious FastAPI serialization case.
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 one optional parameter, an output schema, and read-only/idempotent annotations, the description is complete enough for an agent to invoke it confidently. It covers what it detects, how detection works, when findings will not appear, and what the argument means. Nothing essential is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description carries the full burden for the single search_path parameter. It explains that it is the directory to scan and that it defaults to the configured project. This is useful and sufficient for a simple optional path parameter, though it does not discuss path format or relative-versus-absolute resolution.
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 strongly and concretely conveys what the tool addresses: SQLAlchemy lazy-loading that fetches one row at a time, with both a loop-based and a FastAPI serialization example. It is not a tautology, but it never states an explicit verb like 'detects' or 'reports' for the tool itself, and it does not explicitly differentiate itself from sibling tools such as serializer_nplusone or find_n_plus_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 description gives clear context: the tool works at runtime by watching lazy loads, so the relevant code path must actually execute. It also provides an explicit when-not: relationships declared lazy='selectin', 'joined', or 'raise' are never reported. It does not name alternative sibling tools or give a direct 'use this when...' statement, 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.
suggest_fixesARead-onlyIdempotent
Findings turned into code, grouped by how safe each one is to apply.
Three classes, and the distinction is the point:
- **mechanical**: one correct answer derivable from the code alone, such as
datetime.now() becoming timezone.now(). No judgement in it.
- **generated**: a machine can write the artefact, a human decides whether
it should exist. An index migration is exactly right as text and entirely
wrong if that table is write-heavy.
- **advisory**: real code with the right names resolved, but the decision
belongs to somebody who knows the domain. Which user owns a row is not a
question the AST can answer.
Nothing is applied. The CLI `fix --write` applies the mechanical class only.
Args:
tenant_root: the model that owns data, for the ownership suggestions.
| Name | Required | Description | Default |
|---|---|---|---|
| tenant_root | No | auth.User |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already mark the tool as read-only, idempotent, and non-destructive; the description adds 'Nothing is applied' and the important nuance that the CLI fix --write applies only the mechanical class. This clearly conveys that the tool only returns grouped suggestions and does not mutate anything itself.
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 longer than average but every sentence earns its place: purpose, the three safety classes with concrete examples, and the critical no-apply/CLI caveat. The structure makes the safety taxonomy immediately readable and front-loads the core purpose.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the output schema and annotations, the description does not need to spell out the return shape. It covers purpose, safety taxonomy, non-mutation, CLI behavior, and parameter meaning; only the relationship to sibling diagnostic tools is left implicit.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema provides only the parameter name, type, and default, while the description adds that tenant_root is 'the model that owns data' and that it exists 'for the ownership suggestions.' This compensates well for the 0% schema coverage, though the phrase 'owns data' could be more precise.
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 'Findings turned into code' plus the three safety classes clearly defines suggest_fixes as a code-fix suggester grouped by safety. It distinguishes itself from the diagnostic sibling tools by producing actionable code rather than analysis, but it never explicitly names any sibling 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?
The description explains what the tool does and adds a CLI caveat about how fixes are applied, but it never states when to choose this tool over the many sibling diagnostic tools. There is no explicit when-to-use or 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.
unused_eager_loadingARead-onlyIdempotent
select_related and prefetch_related the serializer never reads.
Every tool in this space looks the other way: a relation the serializer
touches that the queryset did not prefetch, which is the N+1. This is the
opposite, and it costs on every request. An unused select_related is a
JOIN on every row; an unused prefetch_related is a whole extra query plus
the objects it returns.
It is invisible because it looks like an optimisation, and it usually was
one - the field it was added for was removed and nobody takes the line out,
because removing one feels riskier than leaving it in.
nplusone finds this at runtime by watching which loaded objects go
untouched, so it covers the paths the tests exercise. Both halves are in
the source: the queryset says what it loads, the serializer what it reads.
Args:
include_low_confidence: also report views whose serializer has a
SerializerMethodField or which override list/retrieve/
to_representation, where the relation may be read out of sight.
| Name | Required | Description | Default |
|---|---|---|---|
| include_low_confidence | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, and non-destructive behavior, and the description does not contradict them. It adds useful behavioral context: it reports views, optionally includes low-confidence cases, and infers from source that 'the queryset says what it loads, the serializer what it reads.' The mention of nplusone runtime detection introduces slight ambiguity, but the overall behavior is transparent.
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 purpose and then builds context efficiently. It is longer than strictly necessary, but the background about cost, invisibility, and the contrast with N+1 tools earns its place. The Args section is clearly separated and readable.
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, read-only analysis tool, the description covers what it detects, why it matters, how it relates to siblings, and the meaning of the only parameter. An output schema exists, so return details need not be described. The only minor gap is that the runtime versus source-based approach could be stated more directly.
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 schema provides only a boolean with a default, but the description explains exactly what include_low_confidence means: report views with SerializerMethodField or overridden list/retrieve/to_representation where the relation may be read indirectly. This goes well beyond the schema and is essential for correct invocation.
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, 'select_related and prefetch_related the serializer never reads,' identifies the exact resource and issue with a specific verb implied by the tool's name and the surrounding explanation. It also explicitly distinguishes itself from the common N+1 family: 'This is the opposite,' so an agent cannot confuse it with sqlalchemy_nplusone or serializer_nplusone.
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 clear context for when the tool is relevant: unused eager loading costs on every request and looks like an optimization. It contrasts this with N+1 tools, implying use this when the queryset over-loads relations the serializer never reads, though it never explicitly names an alternative tool or states a direct 'use this instead of X' rule.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
what_happens_onARead-onlyIdempotent
Follow the signal chain a save or delete actually triggers.
Nothing at an `order.save()` call site hints that it also writes an Invoice,
clears a cache and queues a task, because the receivers live elsewhere and
were connected in AppConfig.ready(). Tools that list registered receivers
exist; this follows the chain, because the second hop is where the surprise
lives.
It is also the other half of delete_impact, which deliberately ignores
signals and says so.
Args:
model_label: "app_label.ModelName".
event: "save" or "delete".
max_depth: how far to follow writes into further signals.
| Name | Required | Description | Default |
|---|---|---|---|
| event | No | save | |
| max_depth | No | ||
| model_label | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, and destructiveHint, so the description's main behavioral contribution is contextual: it follows chains beyond the first hop and reveals indirect writes, cache clears, and queued tasks. It does not contradict the annotations and adds useful detail about how far the tool reaches.
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 moderately long but well-structured: purpose, motivation, differentiation, then a compact Args list. The AppConfig.ready() example adds context that helps an agent understand why this tool exists, and the final paragraph cleanly lands the parameter semantics. Slightly more verbose than necessary, but no real 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?
Given the presence of an output schema, the description does not need to detail return values. It provides the tool's domain, the kind of outcome to expect (following signal chains), and complete parameter guidance. For a read-only analytical tool with these annotations, nothing essential is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With 0% schema description coverage, the description carries the full burden of documenting parameters. It does so clearly: model_label gets an exact format ('app_label.ModelName'), event gets allowed values ('save' or 'delete'), and max_depth gets an explanation about following writes into further signals. This fully compensates for the sparse 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?
The description opens with a specific verb and resource: 'Follow the signal chain a save or delete actually triggers.' It immediately distinguishes itself from receiver-listing tools and positions itself as the counterpart to delete_impact, so a reader can tell exactly what this tool does and what it is not.
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 clearly explains when this tool is the right choice: when you need to trace the transitive signal-driven effects of a save or delete, because 'the second hop is where the surprise lives.' It explicitly contrasts with delete_impact, which ignores signals, providing a concrete alternative and exclusion.
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 tool update
v0.1.4- Added
defeated_prefetches
36 tool updates
v0.1.3- First observed
amplification - First observed
api_contract - First observed
api_contract_check - First observed
blocking_in_async - First observed
bypassed_effects - First observed
celery_arguments - First observed
check - First observed
choice_typos - First observed
dangling_references - First observed
datetime_audit - First observed
delete_impact - First observed
deploy_safety - First observed
endpoint_cost - First observed
escaping_side_effects - First observed
explain_model - First observed
fastapi_exposure - First observed
find_n_plus_one - First observed
find_unscoped_queries - First observed
list_models - First observed
migration_risk - First observed
missing_indexes - First observed
money_precision - First observed
multiplied_aggregates - First observed
open_endpoints - First observed
project_info - First observed
project_profile - First observed
queries_in_loops - First observed
race_conditions - First observed
request_impact - First observed
scan_templates - First observed
serializer_exposure - First observed
serializer_nplusone - First observed
sqlalchemy_nplusone - First observed
suggest_fixes - First observed
unused_eager_loading - First observed
what_happens_on
TDQS
Scored across 37 tools
Several tools cluster around related concerns—N+1 queries (defeated_prefetches, unused_eager_loading, serializer_nplusone, sqlalchemy_nplusone, find_n_plus_one, scan_templates, queries_in_loops) and API exposure (api_contract, serializer_exposure, open_endpoints, amplification, fastapi_exposure). The individual descriptions do differentiate them, but an agent assembling a workflow would need to read carefully to avoid selecting a near-miss tool.
All names are snake_case and largely domain-specific, but they mix grammatical forms: noun phrases (project_info, endpoint_cost, missing_indexes), past participles (bypassed_effects, multiplied_aggregates), and bare verbs (check, explain_model). Related concepts are phrased inconsistently (find_n_plus_one vs serializer_nplusone vs defeated_prefetches), so the convention is readable but not predictable.
37 tools is well beyond the 'heavy' range and several could be consolidated (notably the N+1 cluster and the exposure/serializer cluster). The broad framework coverage (Django, DRF, FastAPI, SQLAlchemy, Celery) explains part of the size, but it makes the surface feel bloated rather than focused.
For a static analysis/linter server, the surface is remarkably broad: migrations, serializers, security, tenant-scoping, deletion cascades, signals, datetime, indexes, aggregates, and async/Celery pitfalls are all covered. Minor gaps exist—there is no direct MCP tool to apply fixes or manage snapshots beyond check and suggest_fixes—but no core workflow feels like a dead end.
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Connectors
Zero-config MCP security scanner for AI-generated apps. 25K+ vulnerability patterns.
Security, SEO and AI-visibility scanner for web apps · free scans and focused checks via MCP.
Scan any public GitHub MCP-server repo for security issues. 37 MCP-specific L1 rules, 8 languages.
295k+ bug-fix patterns with MCP Hub proxy, PII filtering, and code search
Related MCP Servers
- FlicenseBqualityCmaintenanceEnables comprehensive security vulnerability scanning and code quality analysis for Python applications. Provides detailed reports with scoring, actionable suggestions, and comparison tracking specifically designed for backend developers working with frameworks like Django, Flask, and FastAPI.51-
- AlicenseNot gradedqualityBmaintenanceDev intelligence layer that builds a knowledge graph from any codebase and exposes 7 MCP tools for graph-powered reasoning, impact analysis, and preflight safety and governance checks.32Apache 2.0
- AlicenseNot gradedqualityAmaintenanceMCP server for static analysis of multi-tenant SaaS and MCP server code, catching cross-tenant data leakage. Provides tools to scan code, list/explain rules, and manage suppressions.3,9564MIT
- AlicenseNot gradedqualityBmaintenanceEnables security scanning of source code and Apple configuration files, providing evidence-based findings, explanations, remediation plans, threat modeling, and knowledge base access through MCP tools.MIT