Local multi-repo code-graph MCP server for static analysis, cross-repo exploration, and call-graph navigation using tree-sitter
Koragraph demonstrates strong naming conventions (verb-first: explore, search_code, neighbours, blast_radius, changes_with, file_symbols, recall, remember, dead_code) and comprehensive parameter descriptions. All 10 tools have detailed, LLM-optimized descriptions (100-300 chars) explaining WHAT, WHEN, and WHY. Input schemas are fully specified with proper JSON Schema types, enums, and constraints. Tool annotations (readOnlyHint, destructiveHint, idempotentHint) are present on all tools. However, output schemas are NOT documented, the source shows input contracts but no return type definitions. Error handling guidance is absent from tool descriptions. The 'remember' tool (write operation) lacks confirmation/dry-run pattern. Parameter descriptions are excellent but some edge cases (e.g., detail enum values) could benefit from usage examples.
Before you edit a file, what depends on it? Returns the declarations that would be affected by changes to the file you name — the ones that import it, call its exports, or inherit from its types. Answers "what breaks if I change this file?". Includes both same-repo and cross-repo dependents. The changed-files list is the file-grain annotation plane (see file_symbols for the same annotation type).
What else changed when this symbol changed? Returns declarations that were edited in the same commits as your symbol — a statistical co-change plane mined from git history. Answers "what else might I need to change?" and "what is coupled to this?". Measured on the repository this symbol lives in; cross-repo co-change is not measured.
What declarations are never called? Returns declarations with no inbound edges — code that is defined but never used. Answers "what can I delete?" and "what is dead weight?". Decorated declarations (marked with @Test, @Scheduled, @app., route, etc.) are excluded by default because they are called by frameworks, not by code.
Start here for the code itself, before grep/Read/find — call recall first if the symbol or an error looks like it might have bitten before. One call answers "how does X work / where do I change it": returns the ranked declarations for your query AND, for the top hits, their source, callers, and callees together — so you rarely need to open files, grep, or chain other tools. Use a symbol name or a plain-English phrase.
Output schemas not documented. Tool descriptions explain inputs but do not specify return types, fields, or structure. LLMs cannot plan downstream tool calls or extract chaining IDs without knowing what fields to expect.
No error handling guidance in tool descriptions. Tools do not explain what errors are retryable, user-fixable, or fatal, or what the LLM should do next on failure.
remember tool (write operation) lacks confirmation or dry-run pattern. Agents can record facts without preview or confirmation, risking incorrect knowledge base entries.
Inferred effective spec: 2025-06-18+.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | C | 66 | 2025-06-18+ | v2 |
What is in this file? Returns every declaration in the file, ranked by type and position. Answers "what does this file export / define?" and "where in this file is X?". The file-grain annotation plane (see blast_radius for the same annotation type).
What is directly connected to this symbol. Answers "what calls this?" (direction "in") and "what does this call?" (direction "out"); both by default, because the inbound direction is the one you cannot get by reading the function body. Every relation carries the line it occurs on and how it was resolved, so you can tell a resolved call from an inferred one. Guess-grade edges (HEURISTIC_CALLS), statistical co-change, and a declaration's own structural membership (DEFINED_IN/CONTAINS — what is inside/around it) are excluded unless you ask for them; for co-change use changes_with instead. On a CLASS/SERVICE/INTERFACE symbol, direction "in" also reaches real callers of that type's own methods, not just direct references to the type itself — the common case for "what depends on this class". To trace a call chain, set depth > 1 and direction "out" (or "in" going backward) rather than calling neighbours again on each hop's result — one call then walks several hops and returns them tagged by hop number.
What repositories and projects does the graph hold? Returns the list of projects and repositories indexed on this machine, and the counts of declarations and edges in each. Answers "what am I working with?" on a first turn in an unfamiliar setup. Call this once per session to learn the project names you pass to project_id on other tools.
What has this repository learned the hard way? Returns facts recorded about this codebase — failed attempts and their fixes, hazards, reverts, rules the developer stated — anchored to the declarations they concern. Answers "has this bitten before?" and "what does the team know about this?". Call this FIRST, before explore or search_code, whenever a symbol is unfamiliar or an error looks like it might have bitten before. Silence means nothing was recorded, not that nothing happened.
Record a fact about this codebase. Answers "how do I record what I just learned?". Call this when the developer tells you how things are done here, corrects you, or says "remember that" or "note that" — and when you spent real effort discovering something the code does not say. Prefer it over writing a note into a file: a fact recorded here is anchored to the declaration it is about and expires by itself when that code changes, so recording something is not a promise to maintain it.
Find declarations by name, path, or description — before grepping the source tree. Answers "where is the code that does X?". Returns declarations with file paths and line numbers, ranked; it does not return source bodies — read the files yourself. This is the entry point: every other tool takes a symbol or a path you get from here.
Parameter 'detail' enum values ('concise', 'full') are documented but lack guidance on when to use each. LLMs may not know when to request 'full' detail vs accepting 'concise' default.
No pagination guidance for tools returning lists (search_code, neighbours, dead_code). Descriptions do not explain result limits, how to request more results, or whether results are truncated.