Skip to main content
Glama

archy_impact

Identify which internal modules are impacted by changes to specific files before refactoring. Returns the blast radius and propagation cost to assess structural consequences.

Instructions

Given a list of changed file paths, return the internal modules that transitively import any of them (the blast radius). Use before refactoring or removing a module to see what would break. Files that don't resolve to any module in the graph are returned in unresolved. propagation_cost is the MacCormack-style blast-radius scalar: fraction of the project's internal module count that this edit set can reach (changed plus impacted, over total internal modules). Higher values mean the edit is more structurally consequential.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
pathYes
filesYes

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault
changedYes
unresolvedYes
impactedYes
propagation_costNo

Implementation Reference

  • Tool registration in FastMCP server - registers 'archy_impact' with its name, description, and signature (path + files list, returns Impact model).
    @server.tool(
        name="archy_impact",
        description=(
            "Given a list of changed file paths, return the internal modules "
            "that transitively import any of them (the blast radius). Use "
            "before refactoring or removing a module to see what would break. "
            "Files that don't resolve to any module in the graph are returned "
            "in `unresolved`. `propagation_cost` is the MacCormack-style "
            "blast-radius scalar: fraction of the project's internal module "
            "count that this edit set can reach (changed plus impacted, over "
            "total internal modules). Higher values mean the edit is more "
            "structurally consequential."
        ),
    )
    def archy_impact(
        path: str,
        files: list[str],
    ) -> Impact:
        return _run_impact(Path(path), files=[Path(f) for f in files])
  • Handler function that delegates to find_impact. Builds the import graph, resolves relative file paths against the project root, then calls find_impact.
    def _run_impact(path: Path, *, files: list[Path]) -> Impact:
        graph = _load_graph(path, internal_only=True)
        resolved = [path / f if not f.is_absolute() else f for f in files]
        return find_impact(graph, resolved)
  • The Impact output model (pydantic BaseModel) with fields: changed (resolved modules), unresolved (files not in graph), impacted (modules transitively depending on changed ones), propagation_cost (MacCormack-style blast-radius scalar).
    class Impact(BaseModel):
        model_config = ConfigDict(frozen=True)
    
        changed: tuple[str, ...]
        unresolved: tuple[str, ...]
        impacted: tuple[str, ...]
        propagation_cost: float = 0.0
  • Helper function that builds a mapping from absolute file paths to module qualnames, used to resolve the input file list to graph nodes.
    def _index_by_path(graph: nx.DiGraph) -> dict[Path, str]:
        out: dict[Path, str] = {}
        for qualname, data in graph.nodes(data=True):
            if data.get("external"):
                continue
            raw = data.get("path")
            if raw:
                out[Path(raw).resolve()] = qualname
        return out
  • Core implementation of blast-radius analysis. Resolves file paths to module qualnames, finds all transitive dependents (ancestors in the directed graph), computes propagation_cost as the fraction of internal modules reachable, and returns an Impact result.
    def find_impact(graph: nx.DiGraph, files: list[Path]) -> Impact:
        """Resolve `files` to qualnames and return everything that depends on them.
    
        `impacted` is the set of internal modules with a directed path to any
        changed module (via `nx.ancestors`), minus the changed set itself.
        `propagation_cost` is `(|changed| + |impacted|) / N_internal`: the
        fraction of the project's internal module count that this edit set
        can reach (the two sets are disjoint by construction), a MacCormack-
        style blast-radius scalar. Output tuples are sorted for deterministic
        JSON.
        """
        path_to_qualname = _index_by_path(graph)
    
        changed: set[str] = set()
        unresolved: list[str] = []
        for f in files:
            resolved = f.resolve()
            qualname = path_to_qualname.get(resolved)
            if qualname is None:
                unresolved.append(str(f))
            else:
                changed.add(qualname)
    
        impacted: set[str] = set()
        for q in changed:
            if q in graph:
                impacted |= nx.ancestors(graph, q)
        impacted -= changed
        impacted = {q for q in impacted if not graph.nodes[q].get("external")}
    
        internal_count = sum(1 for _, d in graph.nodes(data=True) if not d.get("external"))
        reachable = len(changed) + len(impacted)
        propagation_cost = (reachable / internal_count) if internal_count else 0.0
    
        return Impact(
            changed=tuple(sorted(changed)),
            unresolved=tuple(sorted(unresolved)),
            impacted=tuple(sorted(impacted)),
            propagation_cost=propagation_cost,
        )
Behavior4/5

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

No annotations are provided, so the description carries the full burden. It explains that unresolved files are returned in 'unresolved' and defines 'propagation_cost'. It does not explicitly state read-only status or auth needs, but given usage context, it is fairly transparent.

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

Conciseness5/5

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

The description is concise (5 sentences), front-loads the main purpose, and clearly outlines usage and output details without unnecessary words.

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

Completeness4/5

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

Given the tool's complexity and the presence of an output schema, the description covers the main purpose, usage, and key output fields. It does not mention preconditions like having a module graph built, but overall it is sufficiently complete.

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

Parameters3/5

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

The input schema has 0% description coverage. The description adds meaning for 'files' as 'changed file paths' but does not explain the 'path' parameter. This partial compensation results in a score of 3.

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

Purpose5/5

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

The description clearly states the tool's purpose: given changed file paths, return the transitive import impact (blast radius). It uses specific verbs and nouns, clearly distinguishing it from sibling tools like archy_graph or archy_high_risk_modules.

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

Usage Guidelines4/5

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

The description explicitly advises using this tool before refactoring or removing a module to see what would break. It does not explicitly mention when not to use or name alternatives, but the usage context is clear.

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

Install Server

Other Tools

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/hslee16/archy'

If you have feedback or need assistance with the MCP directory API, please join our Discord server