You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: README.md
+4-3Lines changed: 4 additions & 3 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -2,12 +2,12 @@
2
2
3
3
A graph-native code intelligence layer for Java microservice estates, exposed to LLM agents via the **Model Context Protocol (MCP)**.
4
4
5
-
The system extracts a deterministic property graph from Java source (tree-sitter), stores it in **Kuzu** (graph) alongside a **LanceDB** vector index (chunks), and exposes a deliberately small MCP surface — **four tools**: `search`, `find`, `describe`, `neighbors` — that collapse onto three primitive agent operations: **locate**, **inspect**, **walk**.
5
+
The system extracts a deterministic property graph from Java source (tree-sitter), stores it in **Kuzu** (graph) alongside a **LanceDB** vector index (chunks), and exposes a deliberately small MCP surface — **five tools**: `search`, `find`, `describe`, `neighbors`, `resolve` — that collapse onto three primitive agent operations: **locate**, **inspect**, **walk**.
6
6
7
7
> **What this MCP is:** a **GPS for code navigation**, not a reasoning engine.
8
8
> Agents use a simple loop:
9
9
>
10
-
> 1.**Locate** entry nodes (`search` / `find`)
10
+
> 1.**Locate** entry nodes (`search` / `find`, or identifier-shaped **`resolve`**)
11
11
> 2.**Inspect** what a node is (`describe`)
12
12
> 3.**Walk** one hop at a time (`neighbors`) until enough evidence is gathered
- **[`docs/AGENT-GUIDE.md`](./docs/AGENT-GUIDE.md)** — copy-paste into `QWEN.md` / `CLAUDE.md` / `AGENTS.md`. Covers the four MCP tools, the shared `NodeFilter`, the edge-type taxonomy, required `neighbors` arguments, the ontology glossary (currently **v12**), the recovery playbook, and slash-style aliases.
232
+
- **[`docs/AGENT-GUIDE.md`](./docs/AGENT-GUIDE.md)** — copy-paste into `QWEN.md` / `CLAUDE.md` / `AGENTS.md`. Covers the five MCP tools, the shared `NodeFilter`, the edge-type taxonomy, required `neighbors` arguments, the ontology glossary (currently **v12**), the recovery playbook, and slash-style aliases.
233
233
- **[`docs/skills/java-codebase-explore.md`](./docs/skills/java-codebase-explore.md)** — exploration **strategy** (missions, fallbacks, anti-capabilities, stopping rules); AGENT-GUIDE remains the **operating manual** for tool shapes and recovery.
234
234
- **[`docs/MANUAL-VERIFICATION-CHECKLIST.md`](./docs/MANUAL-VERIFICATION-CHECKLIST.md)** — 7-phase agent-driven verification you run after indexing your real project. Each item has a copy-paste prompt and calibration data from `tests/bank-chat-system`.
| `describe` | Full record + edge counts for one node. For **type** symbols, `edge_summary` may include composed dot-keys (`DECLARES.DECLARES_CLIENT`, `DECLARES.EXPOSES`); for **method** symbols it may include override-axis virtual keys (`OVERRIDDEN_BY`, `OVERRIDDEN_BY.DECLARES_CLIENT`, `OVERRIDDEN_BY.EXPOSES`, `OVERRIDES`). See [`docs/AGENT-GUIDE.md`](./docs/AGENT-GUIDE.md) (`describe`). | `id: str` | `{"id":"sym:com.bank.chat.core.api.ChatController#joinOperator(JoinOperatorRequest)"}` |
246
+
| `resolve` | Identifier-shaped node lookup (symbol / route / client). Returns `status` `one`, `many`, or `none`; prefer over `describe(fqn=…)` when an FQN may collide. See [`docs/AGENT-GUIDE.md`](./docs/AGENT-GUIDE.md) (`resolve`). | `identifier: str`, `hint_kind: "symbol"|"route"|"client" \| null` | `{"identifier":"com.bank.chat.core.api.ChatController","hint_kind":"symbol"}` |
**Operator / diagnostics (not MCP):** use the **`java-codebase-rag`** CLI — lifecycle (`init`, `increment`, `reprocess`, `erase`) plus `meta`, `tables`, `diagnose-ignore`, `analyze-pr`. Rebuilds are slow; the coding agent should not pretend it can reindex via MCP. For lifecycle commands, subprocess progress is written to **stderr** (use **`--quiet`** to suppress it); **stdout** is only the structured result payload.
37
37
@@ -65,7 +65,7 @@ When a method carries **`@CodebaseHttpRoute`** or **`@CodebaseHttpClient`** (inc
65
65
66
66
**Workflow (GPS model):**
67
67
68
-
1.**Locate** — `search` (natural language / fragment) or `find` (structured `NodeFilter`).
68
+
1.**Locate** — `resolve` when you hold an identifier-shaped string; `search` (natural language / fragment) or `find` (structured `NodeFilter`) for discovery.
69
69
2.**Inspect** — `describe(id)` to see the full record and `edge_summary` (per stored edge label `in`/`out` counts, plus optional composed dot-keys for type Symbols — see `describe` below).
70
70
3.**Walk** — `neighbors` in a loop with explicit **`direction`** and **`edge_types`** until you have enough evidence. Multi-hop “trace” and “impact” are **your** reasoning, not a separate tool.
71
71
@@ -75,7 +75,7 @@ Before every MCP tool call, output **one short line**:
Then check *Argument shapes* (real JSON arrays/objects, required `neighbors` fields). If the call returns nothing useful, do not thrash — use the **Recovery playbook**.
@@ -128,7 +128,7 @@ When reading or comparing symbols, method identity uses **FQN + signature**:
128
128
- Simple type names in parentheses (`String`, `List`), generics erased (`List<String>` → `List`).
129
129
- No spaces after commas. No-arg: `()`. Constructor: `#<init>(...)`.
130
130
131
-
Use `search` to recover the stored symbol id / FQN if you only have a simple name.
131
+
Use `resolve` when the simple name (or FQN fragment) is identifier-shaped; use `search` for fuzzy ranked discovery if you need chunk context before you have a stable id.
132
132
133
133
#### D. `neighbors` — required arguments
134
134
@@ -161,9 +161,13 @@ The same `http_method` key filters HTTP verbs on **routes** (server-side declare
161
161
-**`search.query` is not a DSL** — treat it as opaque text scored against the index. Structured predicates belong in `find`.
162
162
-**`neighbors` filters neighbor rows by kind** — the first neighbor whose kind rejects the filter fails the whole call (no per-row silent skip).
163
163
164
-
### Identifier resolution (pre-`resolve`)
164
+
### Identifier resolution
165
165
166
-
For identifier-shaped lookups without a stable graph id or exact symbol FQN, use **`search(query=…)`** for ranked candidates, then **`describe(id=…)`** (or `describe(fqn=…)` when you have an exact FQN) on each promising row until you confirm the right node. A dedicated **`resolve`** tool is planned separately; until it ships, this multi-call pattern is the supported fallback.
166
+
Use **`resolve(identifier=…, hint_kind=…)`** for identifier-shaped inputs: canonical ids (`sym:` / `route:` / `client:`), symbol FQN or suffix, HTTP `METHOD /path`, route path template, client `target_service`, or `target_service` + path prefix pair. Omit `hint_kind` to match across all three node kinds when the string is enough to scope generators.
167
+
168
+
Branch on **`status`** in the response: **`one`** → `describe(id=…)` on the returned `node`; **`many`** → inspect `candidates` (each has a closed **`reason`**, **`score`** for display only, and a **`NodeRef`** including `microservice` when the row has one), pick one, then `describe(id=…)`; **`none`** (well-formed miss) → fall back to **`search(query=…)`** for natural-language or fuzzy discovery. Malformed empty / whitespace identifiers return `success=false` first.
169
+
170
+
Prefer **`resolve` → `describe(id=…)`** over **`describe(fqn=…)`** when an FQN might collide: `describe(fqn=…)` still returns the first graph row and a hint, but `resolve` makes ambiguity explicit.
167
171
168
172
**`source_layer` vs `role`:** On **Client** nodes, `source_layer` records which brownfield or built-in layer produced the client declaration (`builtin`, `layer_a_meta`, `layer_b_ann`, `layer_c_source`, `layer_b_fqn`, …). On **Symbol** nodes, `role` is the inferred architectural stereotype (`CONTROLLER`, `SERVICE`, `REPO`, …). They answer different questions; names stay distinct.
169
173
@@ -175,12 +179,13 @@ Exact allowed values for roles, capabilities, client kinds, etc. live in `java_o
| Fuzzy / NL “where is X” |`search`|`describe` → `neighbors`|
179
184
| All controllers in service S |`find(kind="symbol", filter={"microservice":S,"role":"CONTROLLER"})`|`neighbors` for `CALLS` / `EXPOSES`|
180
185
| List interfaces in service S |`find(kind="symbol", filter={"microservice":S,"symbol_kind":"interface"})`|`neighbors` / `describe`|
181
186
| List HTTP or Kafka entry points |`find(kind="route", filter={...})`|`describe`|
182
187
| List Feign / HTTP clients |`find(kind="client", filter={...})`|`neighbors(..., out, ["HTTP_CALLS"])` if needed |
183
-
| Who calls method M? |Resolve id via `search`or `find`|`neighbors(ids=sym_id, direction="in", edge_types=["CALLS"])`|
188
+
| Who calls method M? |Stable symbol id via `resolve`, `find`, or `search`|`neighbors(ids=sym_id, direction="in", edge_types=["CALLS"])`|
184
189
| What does M call? | Same |`neighbors(..., direction="out", edge_types=["CALLS"])`|
185
190
| Who hits this route? |`find(kind="route", ...)` or route id from logs |`neighbors(ids=route_id, direction="in", edge_types=["HTTP_CALLS","ASYNC_CALLS","EXPOSES"])`|
186
191
| Handler for a route | Have `route_id`|`neighbors(ids=route_id, direction="in", edge_types=["EXPOSES"])`|
@@ -193,10 +198,10 @@ Exact allowed values for roles, capabilities, client kinds, etc. live in `java_o
193
198
194
199
**Rules of thumb:**
195
200
196
-
1.**Graph beats vector for exact structural questions** — do not `search` for “who calls `Foo#bar`” if you can use `find` + `neighbors(in, [CALLS])`.
201
+
1.**Graph beats vector for exact structural questions** — do not `search` for “who calls `Foo#bar`” if you can use `resolve` / `find` + `neighbors(in, [CALLS])`.
197
202
2.**Vector beats graph for fuzzy discovery** — `search` first, then pivot to `describe` / `neighbors`.
198
203
199
-
### Tool reference — four tools
204
+
### Tool reference — five tools
200
205
201
206
#### `search`
202
207
@@ -214,7 +219,7 @@ Exact allowed values for roles, capabilities, client kinds, etc. live in `java_o
214
219
#### `describe`
215
220
216
221
-**Purpose:** Full node payload + `edge_summary`: `in` / `out` counts **per stored graph edge label** (what exists as edges in Kuzu). For **type** Symbols only (`class`, `interface`, `enum`, `record`, `annotation`), the same map may also include **describe-time composed** dot-keys — summaries of member edges, not stored labels — see the next bullets (`DECLARES.DECLARES_CLIENT`, `DECLARES.EXPOSES`); those keys are **not** valid in `neighbors(edge_types=…)`. For **method** Symbols, the map may include **override-axis** virtual keys (`OVERRIDDEN_BY`, `OVERRIDDEN_BY.DECLARES_CLIENT`, `OVERRIDDEN_BY.EXPOSES`, `OVERRIDES`); see **Override-axis keys (method Symbols)** below — also not `EdgeType` literals.
217
-
-**Args:**`id` (symbol, route, or client id) or **`fqn`** (exact symbol FQN when you do not have the graph id). When both are set, `id` wins. For ambiguous identifiers without an exact id/FQN, see **Identifier resolution (pre-`resolve`)** above.
222
+
-**Args:**`id` (symbol, route, or client id) or **`fqn`** (exact symbol FQN when you do not have the graph id). When both are set, `id` wins. For identifier-shaped inputs and FQN collision handling, see **Identifier resolution** above.
218
223
219
224
**Composed `edge_summary` keys (type Symbols).** Keys use dot notation: `<parent_relation>.<projected_relation>`. Two are emitted today:
220
225
@@ -237,6 +242,12 @@ Static methods suppress the entire override-axis rollup. Constructors do not rec
237
242
238
243
These keys are **not** valid `EdgeType` literals — `neighbors(edge_types=["OVERRIDDEN_BY"])` fails at the Pydantic boundary. Use them as hop affordances only.
239
244
245
+
#### `resolve`
246
+
247
+
-**Purpose:** Identifier-shaped lookup across symbols, routes, and clients; returns `status`**`one`**, **`many`**, or **`none`** with optional `node` / `candidates` (see **Identifier resolution**).
-**Tip:** On **`many`**, use per-candidate `NodeRef.id` and `reason`; follow with **`describe(id=…)`**. On **`none`**, use **`search`** for fuzzy discovery.
250
+
240
251
#### `neighbors`
241
252
242
253
-**Purpose:** One hop over explicit edge types; returns **edges** with attributes (`confidence`, `strategy`, `match`, …) and the **`other`** node.
@@ -264,7 +275,7 @@ Source of truth: `java_ontology.py`. Strings are case-sensitive.
264
275
| ------- | ------------ | --- |
265
276
|`neighbors` validation error | Missing `direction` or `edge_types`| Add both explicitly |
266
277
| Empty `neighbors`| Wrong edge type for the node kind, or wrong direction | Check `describe.edge_summary`; `EXPOSES` is Symbol↔Route — direction matters |
267
-
| Cannot find symbol | Wrong id or stale index |`search` with distinctive string; verify `java-codebase-rag meta` (CLI) |
278
+
| Cannot find symbol | Wrong id or stale index |`resolve` / `search` with distinctive string; verify `java-codebase-rag meta` (CLI) |
268
279
|`find` returns too much | Over-broad filter | Add `microservice`, `fqn_prefix`, `path_prefix`, etc. |
269
280
| Route not found | Path mismatch | Use `path_prefix` on `find(kind="route", …)`; check README brownfield routes |
270
281
| Need ontology / rebuild / PR analysis | Wrong layer | Use **`java-codebase-rag`** CLI, not MCP |
Copy file name to clipboardExpand all lines: docs/JAVA-CODEBASE-RAG-CLI.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,6 +1,6 @@
1
1
# `java-codebase-rag` CLI — operator guide
2
2
3
-
The **`java-codebase-rag`** command is the **operator surface** for this bundle: index lifecycle (`init` / `increment` / `reprocess` / `erase`), graph and Lance health (`meta`, `tables`), ignore diagnostics, and PR diff analysis. It is **not** the MCP tool surface (that is `search` / `find` / `describe` / `neighbors` only). For agents driving the MCP server, see [`AGENT-GUIDE.md`](./AGENT-GUIDE.md).
3
+
The **`java-codebase-rag`** command is the **operator surface** for this bundle: index lifecycle (`init` / `increment` / `reprocess` / `erase`), graph and Lance health (`meta`, `tables`), ignore diagnostics, and PR diff analysis. It is **not** the MCP navigation surface (that is `search` / `find` / `describe` / `neighbors` / `resolve` on the MCP server — this CLI is lifecycle and introspection only). For agents driving the MCP server, see [`AGENT-GUIDE.md`](./AGENT-GUIDE.md).
Copy file name to clipboardExpand all lines: docs/skills/java-codebase-explore.md
+4-1Lines changed: 4 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -45,6 +45,8 @@ On any new estate, **enumerate before you search-hunt**:
45
45
2.**`find(kind="client", …)`** — list outbound clients (Feign, `RestTemplate`, Kafka, etc.) and targets.
46
46
3. Optionally **`find(kind="symbol", filter={"role":"CONTROLLER"})`** (or equivalent `NodeFilter`) to anchor web entrypoints.
47
47
48
+
**Identifier-shaped** strings (FQN, `sym:` / `route:` / `client:` id, route path, client target): start with **`resolve`**, then **`describe(id=…)`**. Use **`search`** / **`find`** for discovery when you do not have a concrete identifier yet — not as the primary chain for identifier disambiguation.
49
+
48
50
You cannot reason reliably about cross-service behaviour until these surfaces exist in your working mental model (or you have consciously fallen back to non-MCP discovery).
49
51
50
52
## Mission catalogue
@@ -218,8 +220,9 @@ disagreement as evidence of staleness, not as a contradiction.
0 commit comments