Local and self-hosted code context graph with MCP, annotation search, and Tree-sitter parsing
18 tools with comprehensive schemas and descriptions. Most tools have well-structured input parameters with types and descriptions (baseline: 4 params/tool, this server averages 5-8). Tool names follow verb_noun convention (parse_project, build_or_update_graph, search, describe, query_graph). Descriptions are detailed (100-400 chars typical, well above 10-char minimum). However, output schemas are not explicitly documented in the source code, only input schemas are visible. Error handling guidance is minimal. No tool annotations (readOnlyHint/destructiveHint) despite clear risk classifications. Some parameter descriptions are verbose but lack actionable constraints (e.g., 'search' query description is 400+ chars but doesn't specify query syntax or examples).
Build or incrementally update the code graph with recursive directory traversal and optional postprocessing
List what the graph holds under one path, exactly and without ranking it. Give it a folder and you get the folders and files directly inside, one level down, each with how many files and declarations are under it. Give it a file and you get every declaration written in it, in the order they appear, each with its line range, its node_id, and its recorded @intent. This is the tool 'search' hands off to: search guesses which declarations matter and can be wrong, this one only reports which exist and cannot be. There is no query, no relevance, no limit, and no empty answer to interpret — a target the graph does not hold comes back as scope 'unknown' with the places that name is actually declared, plus the calls that find it. Start at a folder and descend, or hand it a path from a search hit, a stack frame, or a diff.
Detect changed functions with risk scores based on git diff
Get flows affected by recent code changes
Get annotation and doc tags for a node
Output schemas not documented. Tool descriptions explain inputs but do not specify what fields/structure the response contains. LLMs cannot plan downstream tool calls or extract required data without knowing response structure.
No tool annotations (readOnlyHint/destructiveHint/idempotentHint). Tools are marked with Risk classifications (WRITE, READ_ONLY) in metadata but MCP tool definitions lack formal annotations. Agents cannot determine which tools are safe to retry or have side effects.
Error handling guidance absent. No tool description explains what to do if a query fails, a namespace is not found, or a git operation times out. Agents have no recovery path.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | C | 63 | 2026-07-28+ | v2 |
Get the content of a documentation file by its path. When namespace is specified, reads from {namespace_root}/{namespace}/{file_path}.
Get blast-radius analysis for a node via BFS traversal
Get ultra-compact context for any task (~100 tokens). Always call this first.
Get a node by its qualified name
List materialized ccg:// cross-namespace references for a namespace, as a repository-level dependency map
List all stored flows with member counts
Get graph statistics: total nodes, edges, and breakdowns by kind and language
List namespaces that hold graph data with per-namespace node counts, for scoping cross-namespace queries
Parse source files and store nodes/edges in the graph database
Run predefined graph queries over relationships: callers_of, callees_of, imports_of, importers_of, tests_for, inheritors_of. For what is written inside a file or folder, use 'describe' instead — it replaced the children_of and file_summary patterns, which only ever reported a file's own declarations.
Run postprocessing steps independently: rebuild stored flows and/or full-text search indexing
Full-text search across code nodes, grouped by file. It takes both shapes of query: a symbol you can name (an identifier, a type, a package word, or two or three such words together) and a plain-language question ('how does the graph get built', 'why do we verify the webhook signature'). Named symbols require every term in one indexed node. Questions try that precise match first; if it is empty, they retrieve nodes matching any meaningful term and rank nodes higher when they match more distinctive terms. Questions are also scored against reasons authors recorded (@intent and @domainRule), and files those reasons justify are appended after the general matches. The answer is a list of files, and every file it shows it shows whole: all of that file's hits are in its 'hits' array. Every hit carries the evidence for it — the signals the query matched (name, path, intent), the node's own @intent tag, and, for a reason-matched hit, the recorded reason and the words of the question written in it ('reason', 'matched_terms'). Candidates nothing can justify are left out and counted in weak_filtered. Two separate signals say whether this is the whole answer: 'truncated' is true when more files answered the query than this page reached, and 'pool_truncated' is true when the page ended at the edge of the candidates that were fetched rather than at the end of the answer — one file whose hits fill the candidate pool leaves nothing for 'truncated' to count while later files are still waiting. Only both false means the search is complete; while either is true, make the call in 'next', which lists the exact calls that read on. Use 'path' to scope results to a module for token-efficient queries.
Trace call-chain flow starting from a node
Parameter descriptions lack actionable constraints. 'search' query parameter description is 400+ chars but does not specify query syntax (symbol vs. plain-language), examples, or failure modes. Verbose descriptions without constraints waste tokens and confuse LLMs.
Pagination parameters present but incomplete. 'search' and 'query_graph' accept limit/offset but descriptions do not state max values, default behavior on empty results, or whether truncation signals are returned. Agents cannot reliably page through large result sets.