Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,19 @@ Create local symlinks if your editor expects the legacy paths:
`ln -s .agents .cursor` and `ln -s .agents .claude` (both are
gitignored).

### Two audiences, two skill trees

| Directory | Audience | Purpose |
|-----------|----------|---------|
| **`.agents/skills/`** (`.claude/skills/`, `.cursor/skills/`) | Agents **developing** this repo | propose, plan-prompts, pr-open, pr-review |
| **`skills/`** (project root) | Agents **using** this tool on their own codebase | /callers, /routes, /explain-feature, /impact-of, etc. |

`.agents/` skills are loaded by the agent working *on* java-codebase-rag source
code. `skills/` are shipped to consumers — they instruct an agent to call the
MCP tools (`search`, `find`, `describe`, `neighbors`, `resolve`) against an
indexed Java codebase. Do not mix the two: never import consumer skills into
`.agents/skills/` or vice versa.

This repo is a **self-contained stdio MCP server** that serves semantic
+ structural search over a Java codebase. It is a Python project (the
indexer and server). It is **not** a Java project — the
Expand Down
12 changes: 12 additions & 0 deletions skills/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,18 @@ skills/
README.md ← this file
```

## Skill structure

Every SKILL.md follows this structure:

1. **Frontmatter** — `name` and `description` (used by skill discovery)
2. **MCP required** — declares the MCP server dependency and enforces tool usage
3. **Argument contract** — what the skill accepts
4. **Steps** — imperative MCP call chain (each step names the tool to call)
5. **Worked example** — concrete walk-through
6. **Do not** — guardrails against bypassing MCP tools
7. **Out of scope** — boundaries for when to use a different skill

## Relationship to developer skills

Developer workflow skills (propose, pr-review, etc.) live in `.agents/skills/` — they are for contributors working **on** java-codebase-rag. Skills in this directory are for **consumers** using java-codebase-rag to explore their own codebases.
Expand Down
33 changes: 23 additions & 10 deletions skills/callees/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,19 @@ description: Show what a method symbol calls (in-process CALLS). Use when the us

# /callees — Show callees of a method symbol

## MCP required

This skill requires the **java-codebase-rag** MCP server (tools: `search`, `find`, `describe`, `neighbors`, `resolve`).

**You MUST call these MCP tools to answer.** Do not answer from training data, file browsing, or general knowledge. Each MCP call must be preceded by the reasoning preamble:

```
Q-class: <semantic | structured | inspect | walk>
Pick: <tool> Why: <reason>
```

For the full operating manual (NodeFilter keys, edge taxonomy, argument shapes, recovery playbook), read `docs/AGENT-GUIDE.md`.

## Argument contract

Single positional argument: a method **symbol** id (`sym:...` preferred) OR an identifier-shaped string (FQN fragment, method signature) → `resolve(identifier=..., hint_kind="symbol")`.
Expand All @@ -13,16 +26,9 @@ This skill is for **method symbols**. For inbound traffic to an HTTP route, use

## Steps

1. **Resolve.** If the argument starts with `sym:`, use it. Otherwise:
`resolve(identifier=<arg>, hint_kind="symbol")` → on `one`, use `node.id`; on `many`, list `candidates` and stop; on `none`, try `search(query=<arg>, limit=5)` and stop if still empty.
2. **In-process callees:**
`neighbors({ids: <sym_id>, direction: "out", edge_types: ["CALLS"]})`.
Render grouped by edge type; show callee `fqn` + `microservice`.
3. **Optional — outbound HTTP (only when user asks about cross-service calls):**
`neighbors({ids: <sym_id>, direction: "out", edge_types: ["DECLARES_CLIENT"]})`
→ for each client id:
`neighbors({ids: <client_id>, direction: "out", edge_types: ["HTTP_CALLS"]})`.
(Async: `DECLARES_PRODUCER` → `ASYNC_CALLS` on producer ids.)
1. **Resolve.** If the argument starts with `sym:`, use it as the id. Otherwise, call `resolve(identifier=<arg>, hint_kind="symbol")`. On status `one`, use `node.id`; on `many`, list `candidates` and stop; on `none`, call `search(query=<arg>, limit=5)` and stop if still empty.
2. **In-process callees.** Call `neighbors` with `ids=<sym_id>`, `direction="out"`, `edge_types=["CALLS"]`. Render grouped by edge type; show callee `fqn` + `microservice`.
3. **Optional — outbound HTTP (only when user asks about cross-service calls).** Call `neighbors` with `ids=<sym_id>`, `direction="out"`, `edge_types=["DECLARES_CLIENT"]`. For each client id, call `neighbors` with `ids=<client_id>`, `direction="out"`, `edge_types=["HTTP_CALLS"]`. (Async: `DECLARES_PRODUCER` → `ASYNC_CALLS` on producer ids.)

## Worked example

Expand All @@ -33,6 +39,13 @@ You: → resolve(identifier="ChatController#joinOperator", hint_kind="symbol")
→ returns CALLS edges to in-process service methods
→ (optional step 3) neighbors(out, ["DECLARES_CLIENT"]) on sym id, then HTTP_CALLS from client ids

## Do not

- Do not answer from training data or general Java knowledge.
- Do not read source files directly when MCP tools can provide the answer.
- Do not skip MCP calls and guess at results.
- Do not fabricate symbol ids — always obtain them from `resolve`, `find`, or `search`.

## Out of scope

- Recursive callees beyond depth 1 (use `/trace-request-flow` or `/mini-map`).
Expand Down
27 changes: 22 additions & 5 deletions skills/callers/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,19 @@ description: Show who calls a method symbol (in-process CALLS). Use when the use

# /callers — Show callers of a method symbol

## MCP required

This skill requires the **java-codebase-rag** MCP server (tools: `search`, `find`, `describe`, `neighbors`, `resolve`).

**You MUST call these MCP tools to answer.** Do not answer from training data, file browsing, or general knowledge. Each MCP call must be preceded by the reasoning preamble:

```
Q-class: <semantic | structured | inspect | walk>
Pick: <tool> Why: <reason>
```

For the full operating manual (NodeFilter keys, edge taxonomy, argument shapes, recovery playbook), read `docs/AGENT-GUIDE.md`.

## Argument contract

Single positional argument: a method **symbol** id (`sym:...` preferred) OR an identifier-shaped string (FQN fragment, method signature) → `resolve(identifier=..., hint_kind="symbol")`.
Expand All @@ -13,11 +26,8 @@ This skill is for **method symbols**. For inbound traffic to an HTTP route, use

## Steps

1. **Resolve.** If the argument starts with `sym:`, use it. Otherwise:
`resolve(identifier=<arg>, hint_kind="symbol")` → on `one`, use `node.id`; on `many`, list `candidates` and stop; on `none`, try `search(query=<arg>, limit=5)` and stop if still empty.
2. **In-process callers:**
`neighbors({ids: <sym_id>, direction: "in", edge_types: ["CALLS"]})`.
Render grouped by caller `fqn` + `microservice`.
1. **Resolve.** If the argument starts with `sym:`, use it as the id. Otherwise, call `resolve(identifier=<arg>, hint_kind="symbol")`. On status `one`, use `node.id`; on `many`, list `candidates` and stop; on `none`, call `search(query=<arg>, limit=5)` and stop if still empty.
2. **In-process callers.** Call `neighbors` with `ids=<sym_id>`, `direction="in"`, `edge_types=["CALLS"]`. Render grouped by caller `fqn` + `microservice`.

## Worked example

Expand All @@ -27,6 +37,13 @@ You: → resolve(identifier="ChatController#joinOperator", hint_kind="symbol")
→ neighbors({ids: "sym:...", direction: "in", edge_types: ["CALLS"]})
→ returns CALLS edges from in-process callers

## Do not

- Do not answer from training data or general Java knowledge.
- Do not read source files directly when MCP tools can provide the answer.
- Do not skip MCP calls and guess at results.
- Do not fabricate symbol ids — always obtain them from `resolve`, `find`, or `search`.

## Out of scope

- Callers of routes (use `/who-hits-route`).
Expand Down
24 changes: 21 additions & 3 deletions skills/clients/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,26 @@ description: List outbound HTTP clients, optionally filtered by microservice. Us

# /clients — List outbound HTTP clients

## MCP required

This skill requires the **java-codebase-rag** MCP server (tools: `search`, `find`, `describe`, `neighbors`, `resolve`).

**You MUST call these MCP tools to answer.** Do not answer from training data, file browsing, or general knowledge. Each MCP call must be preceded by the reasoning preamble:

```
Q-class: <semantic | structured | inspect | walk>
Pick: <tool> Why: <reason>
```

For the full operating manual (NodeFilter keys, edge taxonomy, argument shapes, recovery playbook), read `docs/AGENT-GUIDE.md`.

## Argument contract

Optional positional argument: microservice name. Omit to list all clients.

## Steps

1. **Find clients.**
- With microservice: `find(kind="client", filter={microservice: <arg>}, limit=100)`.
- Without microservice: `find(kind="client", filter={}, limit=100)`.
1. **Find clients.** Call `find(kind="client", filter={microservice: <arg>}, limit=100)` when a microservice is given, or `find(kind="client", filter={}, limit=100)` when listing all.
2. **Render.** Show each result's `fqn`, `microservice`, `client_kind`, `target_service`, and `id`.
3. **Narrow if needed.** When results are broad, add `client_kind` or `target_service` to the filter.

Expand All @@ -27,3 +38,10 @@ You: → find(kind="client", filter={microservice: "chat-core"}, limit=100)
User: /clients
You: → find(kind="client", filter={}, limit=100)
→ returns all outbound HTTP client nodes

## Do not

- Do not answer from training data or general Java knowledge.
- Do not read source files directly when MCP tools can provide the answer.
- Do not skip MCP calls and guess at results.
- Do not fabricate symbol ids — always obtain them from `resolve`, `find`, or `search`.
24 changes: 21 additions & 3 deletions skills/controllers/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,26 @@ description: List controller classes, optionally filtered by microservice. Use w

# /controllers — List controllers

## MCP required

This skill requires the **java-codebase-rag** MCP server (tools: `search`, `find`, `describe`, `neighbors`, `resolve`).

**You MUST call these MCP tools to answer.** Do not answer from training data, file browsing, or general knowledge. Each MCP call must be preceded by the reasoning preamble:

```
Q-class: <semantic | structured | inspect | walk>
Pick: <tool> Why: <reason>
```

For the full operating manual (NodeFilter keys, edge taxonomy, argument shapes, recovery playbook), read `docs/AGENT-GUIDE.md`.

## Argument contract

Optional positional argument: microservice name. Omit to list all controllers.

## Steps

1. **Find controllers.**
- With microservice: `find(kind="symbol", filter={role: "CONTROLLER", microservice: <arg>})`.
- Without microservice: `find(kind="symbol", filter={role: "CONTROLLER"})`.
1. **Find controllers.** Call `find(kind="symbol", filter={role: "CONTROLLER", microservice: <arg>})` when a microservice is given, or `find(kind="symbol", filter={role: "CONTROLLER"})` when listing all.
2. **Render.** Show each result's `fqn`, `microservice`, and `id`.

## Worked example
Expand All @@ -26,3 +37,10 @@ You: → find(kind="symbol", filter={role: "CONTROLLER", microservice: "chat-cor
User: /controllers
You: → find(kind="symbol", filter={role: "CONTROLLER"})
→ returns all controller symbols across all microservices

## Do not

- Do not answer from training data or general Java knowledge.
- Do not read source files directly when MCP tools can provide the answer.
- Do not skip MCP calls and guess at results.
- Do not fabricate symbol ids — always obtain them from `resolve`, `find`, or `search`.
35 changes: 26 additions & 9 deletions skills/explain-feature/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,31 @@ description: Understand how a feature works end-to-end by tracing from entry poi

# /explain-feature — Understand a feature end-to-end

## MCP required

This skill requires the **java-codebase-rag** MCP server (tools: `search`, `find`, `describe`, `neighbors`, `resolve`).

**You MUST call these MCP tools to answer.** Do not answer from training data, file browsing, or general knowledge. Each MCP call must be preceded by the reasoning preamble:

```
Q-class: <semantic | structured | inspect | walk>
Pick: <tool> Why: <reason>
```

For the full operating manual (NodeFilter keys, edge taxonomy, argument shapes, recovery playbook), read `docs/AGENT-GUIDE.md`.

## Argument contract

Single positional argument: free-form text describing the feature or concept to explain.

## Steps

1. **Locate entry points.**
`search(query=<arg>, limit=8)` → pick top 1–3 hits with strong `symbol_id` fit (role, `symbol_kind` alignment).
2. **Inspect each hit.**
`describe(id=<symbol_id>)` → read `edge_summary` to understand the node's connectivity.
3. **Walk with bounded neighbors.**
For each inspected node, use `neighbors` with **small** `edge_types` sets per step:
- Methods: `neighbors(out, ["CALLS"])` for in-process flow.
- Boundaries: `EXPOSES` for route handlers; `DECLARES_CLIENT` → `HTTP_CALLS` for outbound HTTP; `DECLARES_PRODUCER` → `ASYNC_CALLS` for async.
- Type wiring: `IMPLEMENTS`, `INJECTS` when relevant.
1. **Locate entry points.** Call `search(query=<arg>, limit=8)`. Pick top 1–3 hits with strong `symbol_id` fit (role, `symbol_kind` alignment).
2. **Inspect each hit.** Call `describe(id=<symbol_id>)` for each hit. Read `edge_summary` to understand the node's connectivity.
3. **Walk with bounded neighbors.** For each inspected node, call `neighbors` with **small** `edge_types` sets per step:
- Methods: call `neighbors` with `direction="out"`, `edge_types=["CALLS"]` for in-process flow.
- Boundaries: call `neighbors` for `EXPOSES` (route handlers), `DECLARES_CLIENT` → `HTTP_CALLS` (outbound HTTP), `DECLARES_PRODUCER` → `ASYNC_CALLS` (async).
- Type wiring: call `neighbors` for `IMPLEMENTS`, `INJECTS` when relevant.
4. **Render.** Synthesize findings into a narrative: entry points → key methods → data flow → cross-service boundaries.

## Stop conditions
Expand All @@ -44,6 +54,13 @@ You: → search(query="operator assignment", limit=8)
→ synthesize: "OperatorAssignmentService is an interface with two implementations.
The controller calls it via DI. It delegates to OperatorRepository for persistence..."

## Do not

- Do not answer from training data or general Java knowledge.
- Do not read source files directly when MCP tools can provide the answer.
- Do not skip MCP calls and guess at results.
- Do not fabricate symbol ids — always obtain them from `resolve`, `find`, or `search`.

## Out of scope

- Exact impact analysis (use `/impact-of`).
Expand Down
27 changes: 22 additions & 5 deletions skills/handlers/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,27 @@ description: Show the method that handles an HTTP or messaging route. Use when t

# /handlers — Show handler method for a route

## MCP required

This skill requires the **java-codebase-rag** MCP server (tools: `search`, `find`, `describe`, `neighbors`, `resolve`).

**You MUST call these MCP tools to answer.** Do not answer from training data, file browsing, or general knowledge. Each MCP call must be preceded by the reasoning preamble:

```
Q-class: <semantic | structured | inspect | walk>
Pick: <tool> Why: <reason>
```

For the full operating manual (NodeFilter keys, edge taxonomy, argument shapes, recovery playbook), read `docs/AGENT-GUIDE.md`.

## Argument contract

Single positional argument: a **route** id (`route:...` preferred) OR an identifier-shaped string (path, METHOD /path) → `resolve(identifier=..., hint_kind="route")`.

## Steps

1. **Resolve.** If the argument starts with `route:` or `r:`, use it. Otherwise:
`resolve(identifier=<arg>, hint_kind="route")` → on `one`, use `node.id`; on `many`, list `candidates` and stop; on `none`, try `find(kind="route", filter={path_prefix: <arg>})` and stop if still empty.
2. **Handler method:**
`neighbors({ids: <route_id>, direction: "in", edge_types: ["EXPOSES"]})`.
Render the handler method `fqn` + `microservice`.
1. **Resolve.** If the argument starts with `route:` or `r:`, use it directly. Otherwise, call `resolve(identifier=<arg>, hint_kind="route")`. On status `one`, use `node.id`; on `many`, list `candidates` and stop; on `none`, call `find(kind="route", filter={path_prefix: <arg>})` and stop if still empty.
2. **Handler method.** Call `neighbors` with `ids=<route_id>`, `direction="in"`, `edge_types=["EXPOSES"]`. Render the handler method `fqn` + `microservice`.

## Worked example

Expand All @@ -28,3 +38,10 @@ You: → resolve(identifier="POST /chat/join", hint_kind="route")
→ route:POST /chat/join
→ neighbors({ids: "route:...", direction: "in", edge_types: ["EXPOSES"]})
→ returns handler method

## Do not

- Do not answer from training data or general Java knowledge.
- Do not read source files directly when MCP tools can provide the answer.
- Do not skip MCP calls and guess at results.
- Do not fabricate route ids — always obtain them from `resolve` or `find`.
Loading
Loading