A comprehensive development workflow orchestration system with MCP servers for memory indexing, graph analysis, and project state management. Provides CLI tools and MCP relays for agents to query governing rules, analyze code dependencies, and manage workflow state.
Strong foundation with 25 tools covering graph analysis, memory indexing, and workflow state. Most tools have clear, actionable descriptions (avg 180 chars) and well-defined schemas with proper enums and constraints. Naming follows verb_noun convention consistently (get_*, query_*, list_*). Key strengths: parameter descriptions are detailed with ranges/constraints; output behavior is documented (truncation, pagination). Weaknesses: no explicit error handling guidance in descriptions; some tools lack output schema documentation; write tools (promote_candidate, reject_candidate, upsert_doc) lack confirmation/dry-run patterns; no tool annotations (readOnlyHint/destructiveHint) despite clear risk profiles.
Compute the depth-2 incoming dependency set for a list of symbols. Returns {effect_size: 'small'|'medium'|'large'|null, direct_dependents, indirect_dependents, modules_touched, god_node_match, ambiguous_bindings}. max_bytes caps the serialized response size (default 60000) via the shape-aware truncator (scalars and effect_size always survive; raw label arrays go first). Use to size a change's risk before dispatching tests.
Graphify-derived blast radius (degraded payload when disabled). Compute the depth-2 incoming dependency set for a list of symbols.
Compare the graph's built_at_commit to git HEAD. Returns {fresh, built_at, head, lag_commits}. Use to decide whether to trust scope_hint signals — if lag_commits > 30, the graph is likely stale.
Return active docs governing a file path (glob-matched via affects_paths). Spans all configured memory roots; rows include source_root.
Return active docs whose affects_symbols includes the given symbol.
Fetch a single doc by id with full content, affects_paths, affects_symbols, links, and keywords.
Write tools lack confirmation/dry-run patterns. promote_candidate, reject_candidate, and upsert_doc are destructive but have no confirmation step or dry-run mode. Agents may irreversibly modify knowledge base without user approval.
No tool annotations (readOnlyHint, destructiveHint, idempotentHint) despite clear risk profiles. Tools like blast_radius and god_nodes are read-only; write tools are destructive. Annotations would help clients enforce safety policies.
Error handling descriptions missing. No tool description explains what errors can occur, how to recover, or whether errors are retryable. LLMs cannot self-correct without explicit guidance.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | D | 53 | 2026-07-28+ | v2 |
BFS the graph from a symbol. direction: 'in' (callers), 'out' (callees), 'both' (default). depth: 1-3 (default 1). relation_filter: optional edge-type whitelist (e.g. 'calls'). max_bytes caps the serialized response size (default 60000); when exceeded the response carries truncated:true + the closest-by-depth neighbors retained. Returns up to 200 neighbors with edge relation + confidence. Use for caller-set enumeration before declaring a change safe.
Look up a single node by id or label. Returns degree counts and source_file. Use to disambiguate when a symbol name matches multiple nodes.
Return the top-N highest-degree nodes in the graph (hubs with the most edges). Use to identify architectural bottlenecks and high-risk refactoring targets.
Aggregate graph statistics: {node_count, edge_count, density, trust ∈ {empty, sparse, dense}}. Use to gauge whether to invest tokens in graph queries — sparse graphs return low-confidence neighbor sets.
Enumerate all status:active docs, optionally filtered by domain.
Transitive link expansion from a doc: returns all docs reachable via affects_links up to depth (default 1).
List all REJ (rejected) docs with their search_keywords. Use to understand what topics have been explicitly ruled out.
Run lanes A-H + blast radius; same as CLI. Returns comprehensive pre-flight analysis.
Promote a knowledge candidate (status:candidate) to status:active. Only exposed when DEVT_MCP_ALLOW_WRITES=1.
Full-text search across the memory index. Tokens AND together with prefix matching.
Group FTS5 matches by document `domain` and return only the {domain: count} map. Use when you want to see WHERE in the project the topic is concentrated.
Count FTS5 matches without returning rows. Use when you only need to know IF/HOW MANY docs match a topic, not their contents.
Return top-N most-relevant FTS5 matches as compact rows (id, title, doc_type only). Use for preview/triage before drilling into a specific doc with get_doc.
Resolve free text to candidate graph nodes (label-substring + token match). Returns top-N nodes with degree counts. Use as the FIRST query when you don't have a known symbol yet — feed top results into get_neighbors for traversal.
SELECT-only escape hatch for raw SQL queries against the memory index. Rejects non-SELECT statements, multi-statement payloads, and dangerous tokens (PRAGMA, ATTACH, etc.).
Reject a knowledge candidate (status:candidate) to status:rejected. Only exposed when DEVT_MCP_ALLOW_WRITES=1.
Directed BFS path finder between two symbols. Returns the edge sequence with relation + confidence per hop. Use to answer 'how does X reach Y?' for bug-trace handoffs.
Report graphify availability: 'ready' (graph.json found), 'disabled' (graphify.enabled=false), 'graph_missing' (enabled but no graph built). Call this first when an agent suspects graphify is unavailable.
Create or update a memory document (ADR/CON/FLOW/REJ/LES). Only exposed when DEVT_MCP_ALLOW_WRITES=1.
Output schemas not documented in descriptions. Tools like preflight, query_index, and list_links do not describe their return structure. LLMs cannot plan downstream calls without knowing what fields to expect.
query_index exposes raw SQL escape hatch without clear input validation guidance. Description states 'Rejects non-SELECT' but does not explain what happens on invalid SQL or how the LLM should handle parse errors.