Skip to main content

codenav-mcp

An MCP server that gives AI agents type-resolved Python navigation, backed by ty's language server. Definitions, references and call sites go through real type inference (imports, dependency-injected parameters, dataclass fields), not text grep.

Quick start

ty is installed with the package, so all you need is uv (or pipx):

uvx codenav-mcp

Register it with your MCP host. For Claude Code, from the project root:

claude mcp add codenav -- uvx codenav-mcp

Or add it to a project .mcp.json (Claude Code) or .cursor/mcp.json (Cursor):

{
	"mcpServers": {
		"codenav": {
			"command": "uvx",
			"args": ["codenav-mcp"],
			"env": {
				"CODENAV_MCP_SOURCE_ROOT": "src"
			}
		}
	}
}

In Cursor, also set "CODENAV_MCP_WORKSPACE": "${workspaceFolder}", because Cursor may start MCP servers with your home directory as the working directory.

Tools

Start with the name-based tools:

Tool Answers
symbol_info What is this? Header, hover, definition and references in one call
outline What's in this file? (classes, methods, functions)
callers Who actually calls this function? (call hierarchy, not imports)
implementations Which classes structurally implement this Protocol? (type-checked)
search_symbol Workspace symbol search by name (ranked, capped; optional kind= / path= filters; production code before tests; fuzzy-only hits summarised unless fuzzy=true)
workspace Which directory is being navigated, and why

Then use the position tools once you have a path:line:col:

Tool Answers
hover Type and docs at a position
definition Go to definition (resolves through injected parameters)
references All usages across the workspace
diagnostics ty type-check diagnostics for one file

name and query are accepted as aliases on the name-based tools (port_name / name / query on implementations). A missing or wrong parameter gets a short hint back instead of a validation error. Dotted names may nest (Outer.Inner.method). implementations also takes file_path to pick one port when the name exists in several files, and counts inherited members and dataclass/self.x fields toward a port's required names.

Write tools: change code with a type check before every write

The navigation tools above are read-only. These change code, and share one rule: the edit is applied to in-memory copies first, ty re-checks the edited files and the files importing them, and the response says which diagnostics the edit would add or fix. Nothing is written until that is on the table.

Tool Does
edit Type-checked text edit of a Python file: old_string/new_string or a whole new_text. For anything that is not a whole definition
edit_symbol action="replace" / "insert" / "delete" a function, method or class by name: re-indented to the file's style, PEP 8 spacing, imports=[...] added, syntax-checked. Delete refuses while anything uses the symbol and prunes now-dead imports
rename_symbol Rename across the workspace (imports, aliases, keyword arguments, parameter= for a function's parameter). Also renames what ty's rename misses: overriding methods, super().name() calls, and Protocol members together with the classes that satisfy them (linked=false to opt out). Lists remaining mentions of the old name (untyped accesses, strings, comments, docs; other worktrees are skipped)
change_signature Add / remove / reorder parameters and rewrite every call site (found through ty's references, so injected dependencies and typed attributes work). Overrides follow. *args calls and uses as a value are listed as manual work
move With name: move a module-level function or class to another file with the imports it needs; without it, move or rename the module file_path. Rewrites imports everywhere, drops imports only the moved code used, warns about import cycles
quick_fix Apply ty's own fixes (missing imports) with correct placement; ambiguous fixes are listed instead of guessed
verify_changes After editing with any tool: which type errors the working tree gained or lost since a git revision (default HEAD)
apply_edit / undo_edit Write a previewed edit by id; revert an applied one

One rule for every write tool: it writes when the edit adds no more than max_new_errors (default 0) type errors in the edited files and their importers. Otherwise nothing is written and you get the diagnostics plus an id for apply_edit. apply=false always previews. Hint-level diagnostics (unused, deprecated) are not counted.

Safety rules, enforced in code:

  • Only .py/.pyi files inside the workspace are written; virtualenvs, site-packages, typeshed and symlinks that leave the workspace are refused.
  • A preview remembers the exact bytes of every file; apply_edit refuses if any file changed since. Files are replaced atomically, and a failure part-way restores the ones already written.
  • Every applied edit is undoable (undo_edit) unless the files were changed after it.
  • Output is never written if it is not valid Python.
  • Edits touching more than 40 files need allow_large=true.
  • CODENAV_MCP_READ_ONLY=1 turns every write into a refusal (previews still work).

New files an edit would create are written to disk for the few moments of the type check (ty finds modules through the file system) and removed again, even on errors.

Positions are 1-indexed. column is a UTF-16 character offset (a leading tab counts as one character).

Python only (.py / .pyi).

Which ty runs

  1. The project's own .venv/bin/ty (.venv\Scripts\ty.exe on Windows), so the ty version matches the project's pin and config.
  2. The ty installed alongside codenav-mcp.
  3. ty on PATH.
  4. uvx ty server as a last resort.

Environment

Variable Default Purpose
CODENAV_MCP_WORKSPACE unset: follows the client's MCP roots when they name a worktree of the same git repository, else CLAUDE_PROJECT_DIR, else the working directory Pins the project root (never overridden). See the workspace tool
CODENAV_MCP_SOURCE_ROOT whole workspace Directory scanned for implementations candidates and used to derive dotted import paths (e.g. src)
CODENAV_MCP_READ_ONLY unset 1/true: write tools refuse to write (previews and checks still work)
CODENAV_MCP_EXTRA_SOURCE_ROOTS none Comma-separated directories (e.g. tests) that implementations also scans; matches (test doubles) are listed under a separate heading

Requirements

  • Python ≥ 3.11
  • Installed automatically: mcp, ty, ruff (sorts imports in files a move touched, only where they were already sorted), mcp-nav-shared
  • webnav-mcp: the same kind of navigation for JS/TS/HTML/CSS.
  • Design notes (Protocol conformance probe, positioning, output formats): docs/agent-tooling.md.

Development

Source: github.com/illescasDaniel/codenav-mcp. From a checkout: uv sync --group dev, then uv run codenav-mcp.

License

MIT. See LICENSE.

Metadata

Release files for codenav-mcp 0.2.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for codenav-mcp 0.2.0
File Size Uploaded Provenance Actions
codenav_mcp-0.2.0.tar.gz 64.7 kB Without provenance Details for codenav_mcp-0.2.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for codenav-mcp 0.2.0
File Interpreter ABI Platform Actions
codenav_mcp-0.2.0-py3-none-any.whl Python 3 none any Details for codenav_mcp-0.2.0-py3-none-any.whl

Total release size: 140.9 kB

Release files / codenav_mcp-0.2.0.tar.gz

Download URL codenav_mcp-0.2.0.tar.gz
Size 64.7 kB
Tags Source
SHA-256 checksum
How to use checksums
4b6e341e593b248c7de9f2ada6a67350e624ff391f86c6094ce10336c47c3e7a
BLAKE2b-256 checksum
How to use checksums
4bc3d2680e609ec1702d32b02bc61412f006b3fdd47d6988cbb6bfa224bc8e6f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.13

Release files / codenav_mcp-0.2.0-py3-none-any.whl

Download URL codenav_mcp-0.2.0-py3-none-any.whl
Size 76.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
2317864034c1ca38b46a5a2baca2129ea1b660bc449fb6b3112190dd6959381c
BLAKE2b-256 checksum
How to use checksums
c656d617cd13c92b0d92268ad4ab6193b3ca6c8c5f1bf15bf0b7ecf1873eaf5b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.13

Security for codenav-mcp 0.2.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page