Skip to main content
Glama
syrian963

django-chainsaw-mcp

by syrian963

escaping_side_effects

Read-onlyIdempotent

Find Django transaction.atomic blocks containing side effects like emails, webhooks, or tasks that won't roll back; identify calls needing on_commit to prevent race conditions and data loss.

Instructions

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.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
search_pathNo
include_low_confidenceNo

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault

No arguments

Schema Changelog

Changes observed during successful MCP inspections.

  1. First observedv0.1.3

TDQS

A4.7/5.0
Behavior5/5

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.

Conciseness4/5

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.

Completeness5/5

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.

Parameters5/5

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.

Purpose5/5

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.

Usage Guidelines4/5

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.