codeatlas
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., "@codeatlaswho calls myapp.auth.login in my 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.
codeatlas
Turn a Python codebase into a queryable knowledge graph — for AI agents and
for humans. Point codeatlas at a directory of .py files and it builds an
atlas: every module, class, and function as a node, and the imports,
inheritance, and calls between them as edges. Query the atlas from the
command line, render the module map as a Mermaid diagram, or serve it to an
LLM agent over MCP so the agent can answer "who calls this?" without reading
the whole repository.
Zero third-party dependencies. Python ≥ 3.10. The only parser is the standard
library's ast module — your code is analysed, never executed.
Quickstart
pip install .
codeatlas build path/to/project -o atlas.json
codeatlas stats atlas.json
codeatlas search atlas.json login
codeatlas query atlas.json myapp.auth.login --callers
codeatlas map atlas.json --out graph.mmd
codeatlas mcp atlas.json # serve the atlas to an agent over stdioNo-install use from a checkout:
PYTHONPATH=src python -m codeatlas build path/to/projectRelated MCP server: RepoGraph
What goes into the atlas
atlas.json is plain JSON, easy to diff, grep, or feed to other tools:
{
"nodes": [
{"id": "shop.orders.DiscountedOrder", "kind": "class",
"file": "shop/orders.py", "line": 14,
"docstring_first_line": "An order with a loyal-customer discount."}
],
"edges": [
{"src": "shop.orders", "dst": "shop.pricing", "kind": "imports"}
],
"stats": {"files": 3, "nodes": 9, "edges": 5,
"nodes_by_kind": {"class": 2, "function": 4, "module": 3},
"edges_by_kind": {"calls": 3, "imports": 1, "inherits": 1}}
}Node ids are dotted paths: package.module.Class.method. Node kinds are
module, class, and function (methods are functions under their class).
Edge kinds are imports, inherits, and calls.
Commands
Command | What it does |
| Scan a directory (or single file) and write the atlas |
| Show a symbol, or one relationship as a list |
| Substring search over symbol ids and docstrings |
| Mermaid flowchart of module-level imports |
| Files / nodes / edges, broken down by kind |
| Stdio MCP server (see below) |
Symbols in query do not need to be full ids: an exact id wins, then a
unique dotted suffix, then a simple name.
MCP server mode
codeatlas mcp atlas.json runs a small stdio JSON-RPC MCP server
(initialize, tools/list, tools/call) with four tools:
search_symbols— find symbols by substringcallers_of— who calls a symbolcallees_of— what a symbol callsmodule_deps— what a module imports, and what imports it
Wire it into any MCP-speaking agent and the agent can navigate the codebase structurally — impact analysis before an edit, orientation in an unfamiliar repository — instead of guessing from filenames.
How resolution works (honestly)
Static, name-based analysis has limits. codeatlas uses these heuristics:
Imports are linked only when the dotted path matches a scanned project module (relative imports are resolved against the importing package). Standard-library and third-party imports produce no edge. Imports are collected at module level, including inside top-level
if/tryblocks.Inheritance links a base class when a class with the same simple name (or a matching dotted suffix) exists in the project; a class from the same module wins.
Calls link when the called name matches a project function or method:
self.x()prefers a sibling method of the same class, a barename()prefers a function in the same module, and otherwise the first matching name in the project wins.
That means dynamic dispatch, getattr, decorators that replace functions,
and coincidental same-named helpers can produce missing or wrong call edges.
Treat the atlas as a good map of the territory — not the territory.
Self-scan
codeatlas, scanned with itself (codeatlas build src):
6 files, 51 nodes (6 modules, 2 classes, 43 functions), 64 edges (58 calls, 6 imports).
Development
PYTHONPATH=src python -m unittest discover -s tests24 tests cover the scanner (a fixture package with known imports, inheritance, and calls), the query layer, the CLI, Mermaid output, and an MCP round-trip driven through a subprocess.
What is included
src/codeatlas/scanner.py— directory walking andastextractionsrc/codeatlas/graph.py— theAtlasmodel, queries, stats, Mermaidsrc/codeatlas/cli.py— the six subcommandssrc/codeatlas/mcp_server.py— the stdio MCP serverexamples/demo_package/— a three-module package to try it on
Roadmap
Cross-file type-aware call resolution
HTML atlas viewer
Incremental rebuilds
License
MIT — see LICENSE.
Available Tools
4 toolscallees_ofC
List symbols called by the given symbol.
| Name | Required | Description | Default |
|---|---|---|---|
| symbol | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full behavioral burden, yet it says nothing about whether results are direct callees only or transitive, whether the analysis is static or dynamic, or what is returned per call. The only implicit signal is 'List', suggesting a read operation, which is weak evidence for a tool with zero annotation coverage.
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 sentence with no filler and the key relation ('called by') front-loaded. It is appropriately sized for the payload it carries, though it is arguably under-specified rather than truly 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?
With no annotations and no output schema, the description needs to cover return shape and call semantics itself. It establishes the basic query but leaves out transitivity depth, return fields, and symbol identifier format — enough for a minimal call, not enough for confident use in a code-graph toolset.
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 single parameter has 0% schema description coverage, so the description must compensate. It does clarify direction ('called by the given symbol'), which resolves the key ambiguity of which symbol the argument represents, but it says nothing about identifier format (fully qualified name, ID, short name) for a code-graph tool where that matters.
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: 'List symbols called by the given symbol.' The phrasing 'called by' makes it the inverse of the sibling callers_of, so an agent can distinguish direction without opening either schema. It doesn't explicitly name the sibling, which keeps it from a 5.
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 guidance on when to use this versus callers_of, search_symbols, or module_deps, and no statement of prerequisites or exclusions. The agent must infer the use case purely from the tool name and the one-sentence purpose.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
callers_ofC
List symbols that call the given symbol.
| Name | Required | Description | Default |
|---|---|---|---|
| symbol | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations exist, so the description carries the full disclosure burden. It does not state whether results are direct callers only or transitive, whether duplicates or external symbols appear, or even that this is a read-only operation — significant gaps for a tool whose value depends on call-graph semantics.
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 short sentence with no filler, front-loading the action and result type. 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?
With no annotations, no output schema, and an undocumented parameter, the description should compensate but does not. An agent still lacks the symbol naming convention and the direct-vs-transitive call semantics needed to call this 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% for the sole required parameter 'symbol'. The description only restates it as 'the given symbol', giving no hint about expected format (fully qualified name, ID, path) or how to obtain a valid value.
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: 'List symbols that call the given symbol.' This is precise enough to distinguish it from the inverse sibling callees_of by name alone, though it never explicitly references the sibling set.
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, when-not-to-use, or alternative guidance is given. The agent must infer that callees_of is the inverse relation and search_symbols is the way to resolve a symbol first; nothing in the description addresses this.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
module_depsC
Show what a module imports and what imports it.
| Name | Required | Description | Default |
|---|---|---|---|
| module | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations exist, so the description carries the full burden, but it only discloses the bidirectionality of the query. It says nothing about what is returned (file paths, module names, nested edges), what happens when the module is unresolvable, or any limits on result size.
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 with no filler. It is appropriately short, though the brevity comes at the cost of the missing detail noted elsewhere.
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 query tool with no annotations and no output schema, the description should pin down the identifier format and the shape of the result. Neither is covered, so an agent can call it but cannot predict or validate the outcome.
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 the single parameter is bare, so the description must clarify whether 'module' means a name, a dotted path, or a file path. It provides none of that, leaving a real ambiguity for a required 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?
States a specific resource (a module) and a specific relationship (imports in both directions), which is enough for an agent to understand the operation. It stops short of naming how it differs from the analogous siblings callers_of and callees_of, which cover the same shape of relationship at a different granularity.
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 guidance on when to use this versus callers_of or callees_of, and no prerequisites or exclusions are stated. The agent must infer the module-level vs symbol-level distinction from the tool names alone.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_symbolsB
Search atlas symbols by substring over ids and docstrings.
| Name | Required | Description | Default |
|---|---|---|---|
| term | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations exist, so the description carries the full behavioral burden. It does disclose genuine matching semantics (substring, across both ids and docstrings), but omits case sensitivity, result limits/pagination, ordering, and what a match returns (a bare id versus a full symbol).
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 front-loaded sentence with no filler; the matching mechanism is stated immediately after the purpose. It is economical, though the terseness leaves little room for the behavioral detail an unannotated tool needs.
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 search tool with no annotations and no output schema, the description should at least sketch the result shape and limits, since none of the structured fields cover them. It covers what is searched but not what comes back or how many results to expect.
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% for the single `term` parameter, so the description must compensate. It partially does by explaining that `term` is matched as a substring against ids and docstrings, but says nothing about format constraints, minimum length, or escaping/glob behavior.
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 ("Search atlas symbols") and adds the matching mechanism ("by substring over ids and docstrings"), which is more than a restatement of the name. It implicitly contrasts with the sibling tools, which are all relation-navigation (callers_of, callees_of, module_deps) rather than discovery, but never names them 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: the substring-over-ids-and-docstrings phrasing hints that this is the lookup/discovery entry point, whereas callers_of/callees_of/module_deps answer relational questions. There is no explicit statement of when to prefer this tool, no prerequisites, and no mention that it is the natural precursor for resolving a symbol before calling the sibling tools.
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.
4 tool updates
v0.1.0- First observed
callees_of - First observed
callers_of - First observed
module_deps - First observed
search_symbols
TDQS
Scored across 4 tools
Each tool targets a distinct operation: substring search, incoming call edges, outgoing call edges, and module-level import edges. The only mild overlap is that callers_of and module_deps both answer 'what depends on this', but the symbol-vs-module scoping in the descriptions keeps them separable.
Three different naming patterns coexist: verb_noun (search_symbols), noun_of relations (callers_of, callees_of), and noun_noun (module_deps). Each name is readable and self-explanatory, but the set does not follow a single predictable convention.
Four tools is minimal but well-scoped for a symbol-graph lookup server; every tool covers a distinct query direction with no filler. It sits at the lean end of the acceptable range rather than feeling padded or arbitrarily thin.
The graph traversal surface is coherent (search, callers, callees, imports), but there is no way to fetch a symbol's details, signature, or location, and no file-level or reference-lookup operation. Agents can navigate the graph but will hit dead ends when they need the symbol itself.
Maintenance
Related MCP Connectors
Hosted code graph over MCP: exact callers, dependencies, and cross-repo blast radius for AI agents.
Ask a codebase what calls what: search, blast radius, paths between symbols, and diffs.
Code intelligence for coding agents: semantic, AST, graph, and full-text search. 279+ languages.
Persistent memory, knowledge graph, task management and more for AI agents via MCP.
Related MCP Servers
- AlicenseNot gradedqualityCmaintenanceEnables AI coding agents to query a codebase as a knowledge graph, providing token-budgeted context, search, and impact analysis via MCP tools.MIT
- FlicenseNot gradedqualityCmaintenanceEnables coding agents to query a local-first code intelligence graph of Python repositories—covering functions, classes, modules, and their relationships—via MCP, supporting subgraph retrieval, caller lookup, and impact analysis without re-reading the codebase.-
- AlicenseNot gradedqualityBmaintenanceEnables AI coding agents to query a local, continuously updated symbol graph of a codebase, providing ranked search, caller/callee exploration, dependency paths, and git-diff impact analysis through MCP tools.1 npmApache 2.0
- AlicenseNot gradedqualityBmaintenanceEnables coding agents to query a local, multi-repo code graph for symbol exploration, blast radius analysis, co-change mining, and durable code-anchored memory via MCP tools.69 npm14Business Source 1.1