impact-mcp
Provides static analysis for JavaScript projects: builds the import graph and answers dependents, dependencies, blast-radius impact, test reachability, affected entry points, import cycles, orphan/hub candidates, and symbol-user questions, with confidence reporting for unresolved or dynamic imports.
Provides static analysis for Python projects: builds the import graph and answers dependents, dependencies, blast-radius impact, test reachability, affected entry points, import cycles, orphan/hub candidates, and symbol-user questions, with confidence reporting for unresolved or dynamic imports.
Provides static analysis for TypeScript projects: builds the import graph and answers dependents, dependencies, blast-radius impact, test reachability, affected entry points, import cycles, orphan/hub candidates, and symbol-user questions, with confidence reporting for unresolved or dynamic imports.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@impact-mcpwhat breaks if I change src/billing/invoice.py, and which tests should I run?"
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.
impact-mcp
Ask "what depends on this file, and what breaks if I change it?" and get an answer that tells you how much to trust it.
impact-mcp is an MCP server that builds the import graph of a Python and/or JavaScript/TypeScript project and answers blast-radius questions: who imports this file, who uses this one symbol, which tests reach it, which entry points are downstream, where the cycles are, what looks dead.
What is different from the other code-graph MCP servers (codegraph-mcp, code-impact-mcp, ts-review-graph, dep-graph-guard and friends):
Zero extra dependencies and fully offline. Only
mcp. Python is read with the stdlibast; JS/TS with a small hand-written tokenizer. No Node, no TypeScript compiler, no ts-morph, no SQLite, no network, nothing executed, nothing written inside your repo.It tells you what it could not see. Every answer ends with a
Graph confidenceline: resolved edges, external packages, unresolved project-looking imports, dynamic non-literal imports, syntax-error files. Dynamicimportlib/import(x)/require(x)is reported as UNRESOLVED, never guessed.impactalso warns when unresolved imports end in the name of the file you are about to change.Python and JS/TS resolution that matches how projects are really laid out:
src/layouts, namespace packages,__init__.pyre-exports and__all__,TYPE_CHECKING, tsconfigextends/baseUrl/paths, monorepo workspace packages,.js->.tsESM style imports,index.tsdirectories,export * from,import type.Symbol-level answers that follow re-exports:
symbol_users("pkg/core.py", "Engine")also finds the file that importsEnginefrom the package__init__.pythat re-exports it.
What it looks like
> impact path=mort/lexer.py
Impact of changing mort/lexer.py
Direct dependents: 2; transitive: 10; max depth: 4
mort/lsp.py -- line 10: from-import {Lexer}
mortc.py [entry] -- line 36: from-import {Lexer}
Tests that reach it through imports (4) - a superset to run, not proof of coverage:
kernel/test_exec.py
tests/test_mort.py
...
Entry points affected (4):
mortc.py (console script in pyproject.toml)
...
Risk: HIGH
- 10 transitive dependent file(s) = 31% of 32 files
- 4 entry point(s) are downstream (a break can surface at startup)
Graph confidence: 32 files (32 py, 0 js/ts) | 52 resolved internal edges | external packages not tracked: 4 (+37 stdlib/builtin) | UNRESOLVED project-looking imports: 0 | dynamic non-literal imports: 0 | syntax-error files: 0Related MCP server: Axon
Install
You need uv. Point --dir at the project you want analyzed.
Claude Code
claude mcp add impact -- uvx impact-mcp --dir /path/to/your/projectClaude Desktop (claude_desktop_config.json)
{
"mcpServers": {
"impact": {
"command": "uvx",
"args": ["impact-mcp", "--dir", "C:\\path\\to\\your\\project"]
}
}
}--dir defaults to the current directory (or IMPACT_MCP_DIR). One server instance analyzes one project.
Tools
Tool | What it answers |
| Languages, module count, packages, guessed entry points, cycle count, unresolved/dynamic imports. Start here. |
| Who imports this file, transitively, grouped by depth, with the import line, names and flags. |
| What this file imports from the project; lists its unresolved and dynamic imports. |
| Blast radius: dependents, tests that reach it, entry points affected, LOW/MEDIUM/HIGH risk with reasons. With |
| Strongly connected components (Tarjan) with the shortest cycle written out edge by edge; notes lazy/type-only edges that soften a cycle. |
| Dead-code candidates (with caveats) and the most depended-on files. |
| Who imports or accesses one name, including through re-exports. Best effort, labeled as such. |
path_or_module accepts a project-relative path (src/app/util.py, packages/ui/src/Button.tsx), a
dotted Python module (app.util), an absolute path inside the project, or an extensionless JS path.
Try asking
"I'm about to change
src/billing/invoice.py. What could break and which tests should I run?""Who uses
parse_configfromapp.config?""Are there import cycles in this repo? Show me the shortest one."
"What are the most depended-on files here? Which files look dead?"
"Which entry points are affected if I rename
Buttoninpackages/ui/src/Button.tsx?""Give me an overview of this project and how much I can trust the import graph."
What it cannot resolve (read this)
The graph is static. These are counted in the confidence line where they are detectable, and the
impact and dependents add hints when they could be hiding a dependent of the file you asked about.
Python
importlib.import_module(name)/__import__(name)with a non-literal argument,exec, plugin discovery by entry points or string names,getattron modules. A literalimport_module("pkg.mod")is resolved and flaggeddynamic.Implicit parent-package execution is not modeled:
import a.b.cis an edge toa/b/c.pyonly, not also toa/__init__.pyanda/b/__init__.py.Which directories act as import roots is inferred (project root,
src/, dirs withpyproject.toml/setup.py, and the dir above each top-level package); a customPYTHONPATHorsys.pathedit is invisible.from x import *is an edge; which names it brings in is taken from__all__/ top-level definitions.Re-exports renamed with
asinside__init__.pyare not followed by symbol tracking.
JavaScript / TypeScript
A tokenizer, not a parser. Known weak spots: JSX text containing an apostrophe can desync the rest of that line; regex-vs-division is heuristic.
require(x)/import(x)with a non-literal argument,require.context, bundler magic (import.meta.glob), Next.js/Nuxt file-system routing.tsconfig:
extendsto an npm package is not followed (warned);references/includeare ignored; the nearest tsconfig.json wins.package.json
exportsis read only for the.entry and simple subpaths (conditions: import, module, default, require, node, types);imports(#alias) maps are reported as unresolved.Workspace packages whose entry is a build output (
dist/) resolve tosrc/equivalents if the source file exists; otherwise the import counts as unresolved.Namespace-import and
requireattribute tracking (ns.foo) is by name only; a namespace passed around as a value marks the edge as "may use anything".Only
.js .jsx .mjs .cjs .ts .tsx .mts .ctsfiles are in the graph;.vue,.svelte,.astroare not.Files over 2 MB (bundles) are skipped and reported.
Both
Symlinks and junctions are not followed (loop safe); skipped counts are reported.
On Windows and macOS (case-insensitive file systems) an import that only matches by case resolves and is counted.
Dead-code candidates are candidates: frameworks, external consumers of a library and non-code tooling can use files the graph cannot see.
Performance
Parsed results are cached by file mtime and size in a cache directory outside your repo
(%LOCALAPPDATA%\impact-mcp on Windows, $XDG_CACHE_HOME/impact-mcp or ~/.cache/impact-mcp elsewhere;
override with IMPACT_MCP_CACHE_DIR). A cold scan of a 2,700-file JS repo takes a few seconds; a warm scan is
dominated by the directory walk. File reading is threaded; .gitignore files (nested too), .git,
node_modules, venv, .venv, dist, build, __pycache__ and similar directories are skipped.
Security
Read-only. Source files are opened for reading and parsed; nothing is imported, executed, installed or written inside the project. The only write is the parse cache, in your user cache directory.
Sandboxed. All paths are resolved against
--dir; absolute paths or..that leave it are rejected. Symlinks are not followed.Offline. No network access of any kind.
Output contains file paths, line numbers, and import names from your code, which go to whatever AI client you connected.
Develop
uv sync --extra test
uv run pytest
uv run --with ruff==0.16.0 ruff check src tests
uv run --with mypy==2.3.0 mypy --strict srcSet IMPACT_TEST_REPOS (paths separated by ; on Windows, : elsewhere) to also run read-only checks against your own repositories.
There is a from-scratch tutorial that builds a minimal version of this server: impact-mcp-the-hard-way.
MIT licensed.
Available Tools
7 toolsdependenciesB
What does this file import from inside the project (transitively up to depth)?
Also lists this file's UNRESOLVED and DYNAMIC imports explicitly.
| Name | Required | Description | Default |
|---|---|---|---|
| depth | No | ||
| limit | No | ||
| path_or_module | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the entire burden. It does disclose real behavioral facts that structured fields do not: results are scoped to project-internal imports only, depth is transitive, and unresolved/dynamic imports are always listed separately. It says nothing about whether the call is read-only, how `limit` truncates or reorders results, or what happens when the path does not exist — gaps that matter for a graph-traversal 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?
Two short sentences, front-loaded with the core question and followed by the one caveat that changes how results should be read. Nothing is wasted and the emphasis on UNRESOLVED/DYNAMIC imports signals that those entries are exceptional.
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?
An output schema exists, so return-value shape need not be described. Still, a zero-coverage three-parameter graph tool needs at least a note on `limit` semantics and the path/module input form; the description stops short of that while adequately covering the transitive-import behaviour.
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 for all three parameters. It only explains `depth` (transitive expansion) and implicitly `path_or_module`; `limit` is never mentioned, and the path-vs-module ambiguity in `path_or_module` is left unresolved.
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 specific question the tool answers: what a given file imports from inside the project, transitively to `depth`, plus unresolved and dynamic imports. That is concrete and materially narrower than a generic graph query. It does not, however, distinguish itself from the obvious inverse sibling `dependents`, which an agent could easily confuse with it.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Use is implied by the framing ('What does this file import...'), so an agent can infer the direction of the lookup. But there is no explicit when-to-use/when-not guidance and no reference to `dependents`, `impact`, or `find_cycles`, which are the near-neighbour alternatives an agent would weigh.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
dependentsA
Who imports this file? Transitive importers grouped by depth, with the import line,
imported names, and flags (type-only / lazy / conditional). path_or_module is a
project-relative path (src/app/util.py, packages/ui/src/Button.tsx), an extensionless JS
path, or a dotted Python module (app.util). Depth 1 = direct importers only.
| Name | Required | Description | Default |
|---|---|---|---|
| depth | No | ||
| limit | No | ||
| path_or_module | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are supplied, so the description carries the full behavioral burden. It discloses what the output contains (grouping, import lines, names, type-only/lazy/conditional flags), which is genuinely informative, but says nothing about whether the whole project is scanned, how unresolved or dynamic imports are handled, or the cost of deep traversal.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the core question, then the output shape, then input formats — a sensible ordering with no filler sentences. The parenthetical path examples are dense but earn their place; slightly tighter phrasing could avoid the line-broken run-on.
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?
An output schema exists, so return-value detail is not strictly required, yet the description spends most of its words on output shape while leaving `limit` and traversal cost unaddressed. For a three-parameter graph-traversal tool with no annotations, the missing coverage of pagination and scan scope is a real gap.
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, and it largely does for the required parameter: it enumerates accepted forms (project-relative path, extensionless JS path, dotted Python module) with concrete examples. `depth` is clarified via 'Depth 1 = direct importers only', but `limit` (default 100) is never mentioned, leaving one of three parameters undocumented.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a concrete verb+resource question ('Who imports this file?') and specifies the shape of the answer (transitive importers grouped by depth, with import lines, imported names, and flags). That is enough to distinguish it from the reverse-direction sibling `dependencies`, but it never names that sibling or `impact`, leaving the agent to infer the inverse relationship.
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?
Useful operational guidance is embedded: accepted `path_or_module` formats and 'Depth 1 = direct importers only', which tells the agent how to get direct-only results. However, there is no explicit statement of when to prefer this over `dependencies`, `impact`, or `project_map`, and no exclusions or prerequisites.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
find_cyclesA
Import cycles: strongly connected components (Tarjan), each with its shortest cycle spelled out file by file, and whether the cycle is softened by lazy/type-only imports.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden and does disclose meaningful behavior beyond the schema: results are strongly connected components, each reduced to a shortest cycle listed file by file, plus a flag for whether lazy/type-only imports soften the cycle. It does not disclose analysis scope or how many components are returned before truncation, which keeps it below 5.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single dense sentence that front-loads the resource ('Import cycles') and then qualifies the output. The parenthetical '(Tarjan)' is useful shorthand, though 'spelled out file by file' is slightly awkward phrasing.
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 is simple (one optional param) and has an output schema, so return values need not be explained here; the description covers purpose and the key nuance of softened cycles. The only real omission is the limit parameter's meaning and default behavior.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
There is one parameter (limit, default 10) with 0% schema description coverage, and the description never mentions it — no indication that it caps the number of cycles reported or what happens when more exist. The description therefore does not compensate for the coverage 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?
States a specific verb+resource ('Import cycles') and goes further by naming the algorithm (Tarjan SCCs) and the shape of each result ('shortest cycle spelled out file by file'). It is clearly distinct from siblings like dependencies or project_map, though it never names an alternative explicitly.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is only implied: an agent can infer it is for circular-import investigation, but there is no statement of when to reach for this versus dependencies/dependents, nor any prerequisite or scope guidance (whole project vs a subtree).
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
impactA
Blast radius of changing a file (or one symbol in it): direct and transitive dependents,
the tests that reach it through imports (run these), entry points affected, and a LOW/MEDIUM/HIGH
risk summary with reasons. With symbol, direct users are narrowed to files that import or
access that name (following re-exports); the rest is an upper bound.
| Name | Required | Description | Default |
|---|---|---|---|
| path | Yes | ||
| limit | No | ||
| symbol | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description must carry the behavioral burden, and it does disclose a genuinely non-obvious trait: when `symbol` is supplied, direct users are narrowed but 'the rest is an upper bound,' telling the agent the output is an over-approximation it must interpret carefully. It also explains the risk-grading output and that reasons accompany it. It does not state that the call is read-only, cheap/expensive, or how `limit` truncates results.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences, front-loaded with the core concept, then outputs, then the parameter caveat. Every clause adds information — the parenthetical '(run these)' directs action and the upper-bound note prevents misreading. No filler or restatement of the tool name.
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?
Output schema exists, so return shape need not be spelled out, yet the description still orients the agent by summarizing result categories and the risk grade, which is appropriate for an analysis tool whose value is interpretive. Against a 3-parameter tool the only real hole is `limit` and the absence of any guidance about result size or truncation.
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% and all three parameters are bare titles, so the description must compensate. It does this well for `symbol` (narrowing to files that import or access the name, following re-exports) and adequately for `path` by framing the whole tool around a file. However, `limit` (default 40) is never mentioned, leaving a truncation parameter with no meaning attached anywhere.
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 specific analysis ('blast radius of changing a file') and enumerates exactly what the result contains: direct and transitive dependents, tests reaching it via imports, affected entry points, and a risk summary. That is far more specific than the bare name 'impact'. It stops short of a 5 because it never names a sibling (dependents, symbol_users) to show where the boundary lies, so the agent must infer that this is the composite/richer variant.
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 decision context ('changing a file') and a concrete follow-up action ('the tests that reach it through imports (run these)'), plus a rule for choosing symbol vs. file-level mode. What is missing is any exclusion or alternative: there is no statement like 'use dependents for a cheap non-risk listing', so an agent cannot rule out the lighter siblings from this text alone.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
orphans_and_hubsB
Dead-code candidates (files nothing imports that are not entry points, tests, init.py or configs - with caveats) and the most depended-on files (direct importers / transitive dependents).
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description must carry the behavioral load, and it does disclose the exclusion rules that shape the orphan list and hints at heuristic unreliability ('with caveats'). However, it never says what those caveats are, whether the two lists are ranked/scored, or what ordering the hub ranking uses – substantial gaps for a heuristic analysis 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?
A single front-loaded sentence that leads with the primary output and packs the exclusion criteria inline. The nested parenthetical is slightly dense but nothing is wasted.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema is present, so return shape needn't be explained, and the description covers what the tool finds and what it filters out. The undisclosed 'caveats' and the missing handling of the limit parameter leave real ambiguity about what an agent will actually receive.
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?
Only one optional parameter exists in the schema, which sets the baseline at 4 regardless of description.
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?
Names two concrete resources – dead-code candidates and most-depended-on files – with the defining criteria (files nothing imports, excluding entry points/tests/__init__.py/configs) and a metric for hubs (direct importers / transitive dependents). It is clearly not project_map or find_cycles, though the hub half overlaps conceptually with the 'dependents' sibling without being explicitly differentiated.
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?
No when-to-use guidance and no routing to alternatives. Given siblings like dependents, impact, and symbol_users, an agent gets no signal about when to pick this combined report over the narrower tools. The 'with caveats' parenthetical flags uncertainty without resolving it.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
project_mapA
Overview of the project: languages, module count, Python packages, guessed entry points (pyproject scripts, main.py, package.json bin/main/exports), import-cycle count, unresolved/dynamic imports, and syntax-error files. Start here.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden, and it does disclose the analysis surface: it reports guessed entry points and the specific files consulted, and it flags unresolved/dynamic imports and syntax-error files, which tells the agent the map is heuristic and may be incomplete. It does not explicitly state that the call is read-only or note cost/scale behavior for large projects, leaving a modest gap.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
One dense enumerative sentence plus the front-loaded imperative "Start here" — close to no waste and the routing cue is prominent. The list is long but each item is a distinct reported datum, so trimming would lose information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema present, the description need not explain return values, and it correctly focuses on scope of analysis and when to call it. For a zero-parameter project overview the definition is nearly complete; only an explicit read-only/side-effect statement and any project-size caveat are 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 tool takes zero parameters, so there is no parameter semantics to explain; the baseline for an empty schema applies. Nothing in the description misleads about inputs.
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 (the project) and enumerates exactly what the overview contains: languages, module count, Python packages, guessed entry points with the heuristics used (pyproject scripts, __main__.py, package.json bin/main/exports), import-cycle count, unresolved/dynamic imports, and syntax-error files. That enumeration also cleanly distinguishes it from the narrower siblings (find_cycles, dependents, dependencies, impact, orphans_and_hubs, symbol_users), which each answer one targeted question.
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?
"Start here" is an explicit sequencing instruction that tells the agent to call this before the targeted siblings, which is meaningful routing guidance for a zero-parameter tool. It stops short of stating exclusions or when a sibling is preferable instead, so it is clear context without full when/when-not coverage.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
symbol_usersA
Who uses symbol from module? Best effort and labeled as such: from-imports, named
imports, attribute access on the module alias (mod.name), wildcard imports, and re-export chains
(init.py, all, export {x} from). getattr()/dynamic use is invisible.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | ||
| module | Yes | ||
| symbol | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden and does substantial work: it enumerates exactly which reference forms are detected (from-imports, named imports, module-alias attribute access, wildcard imports, re-export chains) and explicitly discloses the blind spot for getattr()/dynamic use. That is real behavioral context an agent cannot get from the schema. It stops short of describing result ordering or how the limit interacts with truncation.
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?
Two tight sentences, front-loaded with the core question, followed by the coverage caveat. Every clause adds information; nothing is redundant.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return-value explanation is unnecessary, and the description covers detection scope and known limitations well. The only meaningful gap is the unexplained `limit` parameter and any note on result ordering or truncation behavior.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate. It implicitly clarifies `module` and `symbol` through examples like mod.name and __init__.py, but the `limit` parameter (default 100) is never mentioned, leaving pagination/truncation semantics undocumented.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a precise question form, 'Who uses `symbol` from `module`?', which names both the verb (find users) and the resource (a specific symbol within a module). This is clearly narrower than module-level siblings like dependents or dependencies, though it never names those siblings explicitly to draw the 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?
Usage is implied by the question framing and the 'best effort' caveat signals when results may be incomplete, but there is no explicit when-to-use versus when-to-use-a-sibling guidance (e.g., dependents vs symbol_users) and no stated prerequisites.
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.
7 tool updates
v0.1.0- First observed
dependencies - First observed
dependents - First observed
find_cycles - First observed
impact - First observed
orphans_and_hubs - First observed
project_map - First observed
symbol_users
TDQS
Scored across 7 tools
Each tool targets a distinct analysis: overview, cycles, forward imports, reverse imports, blast radius, hub/orphan stats, and symbol-level usage. The main risk is `dependents` vs `impact` (impact largely subsumes dependents' output plus tests and risk) and the near-homophone pair `dependents`/`dependencies`, which an agent could swap despite direction being stated in the text.
Names are all lowercase snake_case, but grammatical form is mixed: verb phrases (`find_cycles`), bare nouns (`dependents`, `dependencies`, `impact`), and a conjoined noun (`orphans_and_hubs`). The pair `dependents`/`dependencies` is only one character-apart in semantics and spelling, which is a real readability hazard even though no convention is violated outright.
Seven tools is well-scoped for an import-graph/impact-analysis server, with one tool per analysis question rather than redundant variants. Nothing feels padded or missing at the count level.
The surface covers the full lifecycle of impact analysis: orient (project_map), forward/reverse graph queries, cycles, dead code/hubs, symbol usage, and a risk-rated blast radius including affected tests and entry points. Minor gaps: no direct way to locate a file by fuzzy name or browse the test-to-source mapping outside `impact`, and no handling of dynamic/reflective edges beyond flagging them.
Maintenance
Related MCP Connectors
Deterministic context layer for your codebase: change impact, blast radius, answers with receipts.
Ask a codebase what calls what: search, blast radius, paths between symbols, and diffs.
Ask who calls a route, what a change breaks or who reads a field, across a system's repos.
Codebase intelligence for AI agents — dead code, blast radius, ownership.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceEnables querying and analyzing code relationships by building a lightweight graph of TypeScript and Python symbols. Supports symbol lookup, reference tracking, impact analysis from diffs, and code snippet retrieval through natural language.MIT
- AlicenseNot gradedqualityDmaintenanceA graph-powered code intelligence engine that indexes codebases into a structural knowledge graph to provide AI agents with deep context on function calls, types, and execution flows. It offers local, zero-dependency tools for hybrid search, impact analysis, and dead code detection across Python, JavaScript, and TypeScript projects.1,285 PyPI816MIT
- AlicenseNot gradedqualityBmaintenanceEnables AI agents and terminal users to query codebases for callers, impact, tests, dependencies, and refactor previews using static AST analysis, with every match accounted for and uncertain relationships clearly marked.331 npm2MIT
- AlicenseNot gradedqualityAmaintenanceEnables AI coding agents to query a local structural code graph, inspect relationships and impact, and retrieve focused project context before reading full files.66 npmMIT