@infinitedusky/indusk-mcp 0.3.0 → 0.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -196,6 +196,19 @@ export async function init(projectRoot, options = {}) {
196
196
  console.info(" missing: Docker — install Docker or OrbStack to enable FalkorDB");
197
197
  }
198
198
  const cgcInstalled = checkCGC();
199
+ // 9. Auto-index the codebase into the graph
200
+ if (dockerAvailable && cgcInstalled) {
201
+ console.info("\n[Code Graph]");
202
+ console.info(" indexing: scanning codebase...");
203
+ const { indexProject } = await import("../../tools/graph-tools.js");
204
+ const result = indexProject(projectRoot);
205
+ if (result.success) {
206
+ console.info(` done: ${result.output}`);
207
+ }
208
+ else {
209
+ console.info(` error: ${result.output}`);
210
+ }
211
+ }
199
212
  // Summary
200
213
  console.info("\nDone!");
201
214
  if (!cgcInstalled || !dockerAvailable) {
@@ -210,7 +223,6 @@ export async function init(projectRoot, options = {}) {
210
223
  }
211
224
  console.info("\nNext steps:");
212
225
  console.info(" 1. Edit CLAUDE.md with your project details");
213
- console.info(" 2. Install Biome: pnpm add -D @biomejs/biome");
214
- console.info(" 3. Start a Claude Code session — MCP tools will be available");
215
- console.info(" 4. Start planning: /plan your-first-feature");
226
+ console.info(" 2. Start a Claude Code session — MCP tools will be available");
227
+ console.info(" 3. Start planning: /plan your-first-feature");
216
228
  }
@@ -1,5 +1,5 @@
1
1
  import { createHash } from "node:crypto";
2
- import { cpSync, existsSync, readFileSync } from "node:fs";
2
+ import { cpSync, existsSync, mkdirSync, readFileSync } from "node:fs";
3
3
  import { dirname, join } from "node:path";
4
4
  import { fileURLToPath } from "node:url";
5
5
  import { globSync } from "glob";
@@ -14,21 +14,25 @@ export async function update(projectRoot) {
14
14
  const skillsTarget = join(projectRoot, ".claude/skills");
15
15
  const skillFiles = globSync("*.md", { cwd: skillsSource });
16
16
  let updated = 0;
17
- let skipped = 0;
17
+ let added = 0;
18
+ let current = 0;
18
19
  for (const file of skillFiles) {
19
20
  const skillName = file.replace(".md", "");
20
21
  const sourceFile = join(skillsSource, file);
21
- const targetFile = join(skillsTarget, skillName, "SKILL.md");
22
+ const targetDir = join(skillsTarget, skillName);
23
+ const targetFile = join(targetDir, "SKILL.md");
22
24
  if (!existsSync(targetFile)) {
23
- console.info(` skip: ${skillName} (not installed — run init first)`);
24
- skipped++;
25
+ mkdirSync(targetDir, { recursive: true });
26
+ cpSync(sourceFile, targetFile);
27
+ console.info(` added: ${skillName} (new skill)`);
28
+ added++;
25
29
  continue;
26
30
  }
27
31
  const sourceHash = fileHash(sourceFile);
28
32
  const targetHash = fileHash(targetFile);
29
33
  if (sourceHash === targetHash) {
30
34
  console.info(` current: ${skillName}`);
31
- skipped++;
35
+ current++;
32
36
  }
33
37
  else {
34
38
  cpSync(sourceFile, targetFile);
@@ -36,5 +40,5 @@ export async function update(projectRoot) {
36
40
  updated++;
37
41
  }
38
42
  }
39
- console.info(`\n${updated} updated, ${skipped} current.`);
43
+ console.info(`\n${added} added, ${updated} updated, ${current} current.`);
40
44
  }
@@ -3,6 +3,7 @@ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
3
3
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
4
4
  import { registerContextTools } from "../tools/context-tools.js";
5
5
  import { registerDocumentTools } from "../tools/document-tools.js";
6
+ import { registerGraphTools } from "../tools/graph-tools.js";
6
7
  import { registerPlanTools } from "../tools/plan-tools.js";
7
8
  import { registerQualityTools } from "../tools/quality-tools.js";
8
9
  import { registerSystemTools } from "../tools/system-tools.js";
@@ -17,6 +18,7 @@ export async function startServer() {
17
18
  registerQualityTools(server, projectRoot);
18
19
  registerDocumentTools(server, projectRoot);
19
20
  registerSystemTools(server, projectRoot);
21
+ registerGraphTools(server, projectRoot);
20
22
  const transport = new StdioServerTransport();
21
23
  await server.connect(transport);
22
24
  }
@@ -0,0 +1,6 @@
1
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ export declare function indexProject(projectRoot: string): {
3
+ success: boolean;
4
+ output: string;
5
+ };
6
+ export declare function registerGraphTools(server: McpServer, projectRoot: string): void;
@@ -0,0 +1,116 @@
1
+ import { execSync } from "node:child_process";
2
+ import { existsSync } from "node:fs";
3
+ import { basename, join } from "node:path";
4
+ import { z } from "zod";
5
+ function cgcPath() {
6
+ const paths = [join(process.env.HOME ?? "", ".local/bin/cgc"), "/usr/local/bin/cgc"];
7
+ return paths.find((p) => existsSync(p)) ?? null;
8
+ }
9
+ function runCgc(args, projectRoot) {
10
+ const cgc = cgcPath();
11
+ if (!cgc) {
12
+ return JSON.stringify({ error: "CGC not installed — run: pipx install codegraphcontext" });
13
+ }
14
+ try {
15
+ return execSync(`${cgc} ${args}`, {
16
+ encoding: "utf-8",
17
+ timeout: 60000,
18
+ stdio: ["ignore", "pipe", "pipe"],
19
+ cwd: projectRoot,
20
+ env: {
21
+ ...process.env,
22
+ DATABASE_TYPE: "falkordb-remote",
23
+ FALKORDB_HOST: process.env.FALKORDB_HOST ?? "localhost",
24
+ FALKORDB_PORT: process.env.FALKORDB_PORT ?? "6379",
25
+ FALKORDB_GRAPH_NAME: process.env.FALKORDB_GRAPH_NAME ?? basename(projectRoot),
26
+ },
27
+ }).trim();
28
+ }
29
+ catch (err) {
30
+ const execErr = err;
31
+ return JSON.stringify({
32
+ error: execErr.stderr?.trim() || execErr.message || "CGC command failed",
33
+ });
34
+ }
35
+ }
36
+ export function indexProject(projectRoot) {
37
+ const cgc = cgcPath();
38
+ if (!cgc) {
39
+ return { success: false, output: "CGC not installed — run: pipx install codegraphcontext" };
40
+ }
41
+ const graphName = process.env.FALKORDB_GRAPH_NAME ?? basename(projectRoot);
42
+ try {
43
+ // Check if .cgcignore exists
44
+ const hasIgnore = existsSync(join(projectRoot, ".cgcignore"));
45
+ const output = execSync(`${cgc} index ${projectRoot}`, {
46
+ encoding: "utf-8",
47
+ timeout: 120000,
48
+ stdio: ["ignore", "pipe", "pipe"],
49
+ env: {
50
+ ...process.env,
51
+ DATABASE_TYPE: "falkordb-remote",
52
+ FALKORDB_HOST: process.env.FALKORDB_HOST ?? "localhost",
53
+ FALKORDB_PORT: process.env.FALKORDB_PORT ?? "6379",
54
+ FALKORDB_GRAPH_NAME: graphName,
55
+ },
56
+ }).trim();
57
+ return {
58
+ success: true,
59
+ output: `Indexed into graph '${graphName}'${hasIgnore ? " (with .cgcignore)" : " (no .cgcignore — consider creating one)"}. ${output}`,
60
+ };
61
+ }
62
+ catch (err) {
63
+ const execErr = err;
64
+ return {
65
+ success: false,
66
+ output: execErr.stderr?.trim() || execErr.message || "Index failed",
67
+ };
68
+ }
69
+ }
70
+ export function registerGraphTools(server, projectRoot) {
71
+ server.registerTool("index_project", {
72
+ description: "Index the project codebase into the code graph. Run this after init or when the codebase has changed significantly. Uses CGC under the hood.",
73
+ }, async () => {
74
+ const result = indexProject(projectRoot);
75
+ return {
76
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
77
+ isError: !result.success,
78
+ };
79
+ });
80
+ server.registerTool("query_dependencies", {
81
+ description: "Query what depends on a file or module, and what it depends on. Use BEFORE modifying any file to understand blast radius.",
82
+ inputSchema: {
83
+ target: z.string().describe("File path, function name, or module to query"),
84
+ direction: z
85
+ .enum(["dependents", "dependencies", "both"])
86
+ .default("both")
87
+ .describe("Direction: what depends on this (dependents), what this depends on (dependencies), or both"),
88
+ },
89
+ }, async ({ target, direction }) => {
90
+ let query;
91
+ if (direction === "dependents") {
92
+ query = `MATCH (dependent)-[r]->(target) WHERE target.name CONTAINS '${target}' RETURN dependent.name as dependent, type(r) as relationship, target.name as target`;
93
+ }
94
+ else if (direction === "dependencies") {
95
+ query = `MATCH (source)-[r]->(dep) WHERE source.name CONTAINS '${target}' RETURN source.name as source, type(r) as relationship, dep.name as dependency`;
96
+ }
97
+ else {
98
+ query = `MATCH (a)-[r]-(b) WHERE a.name CONTAINS '${target}' RETURN a.name as source, type(r) as relationship, b.name as related ORDER BY relationship`;
99
+ }
100
+ const output = runCgc(`query "${query}"`, projectRoot);
101
+ return {
102
+ content: [{ type: "text", text: output }],
103
+ };
104
+ });
105
+ server.registerTool("query_graph", {
106
+ description: "Run a custom Cypher query against the code graph. Use for advanced structural queries not covered by query_dependencies.",
107
+ inputSchema: {
108
+ cypher: z.string().describe("Cypher query to execute (read-only)"),
109
+ },
110
+ }, async ({ cypher }) => {
111
+ const output = runCgc(`query "${cypher}"`, projectRoot);
112
+ return {
113
+ content: [{ type: "text", text: output }],
114
+ };
115
+ });
116
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@infinitedusky/indusk-mcp",
3
- "version": "0.3.0",
3
+ "version": "0.4.1",
4
4
  "description": "InDusk development system — skills, MCP tools, and CLI for structured AI-assisted development",
5
5
  "type": "module",
6
6
  "files": [
package/skills/context.md CHANGED
@@ -78,6 +78,7 @@ After writing a retrospective, read the "Insights Worth Carrying Forward" and "W
78
78
  - If it changes the project's architecture or structure → update **Architecture**
79
79
  - Update **Current State** to reflect the plan's completion
80
80
  - If the retrospective's "Quality Ratchet" section adds a new Biome rule, also add the enforced pattern to **Conventions**
81
+ - **REQUIRED: Query the code graph** — call `query_dependencies` on the key files that changed to verify the Architecture section still reflects reality. If the plan changed how modules connect, update Architecture with the new relationships.
81
82
 
82
83
  Do this immediately after writing the retrospective, before moving on.
83
84
 
@@ -18,6 +18,8 @@ After context items are done, the document gate asks one question:
18
18
 
19
19
  **"Does this phase change something a user or developer needs to know?"**
20
20
 
21
+ To answer this accurately, **REQUIRED: call `query_dependencies`** on the key files changed in this phase. If the change affects files with many dependents, it likely needs documentation. If it's internal with no downstream consumers, it might not.
22
+
21
23
  - If **yes**: write or update the relevant page in `apps/indusk-docs/src/`
22
24
  - If **no**: skip — not every phase produces documentation. The gate asks the question but doesn't always produce output.
23
25
 
package/skills/plan.md CHANGED
@@ -31,7 +31,12 @@ General-purpose research (insights useful across plans) also lives in `research/
31
31
 
32
32
  1. **Figure out where things stand.** If a plan folder already exists, read what's there. Check frontmatter statuses. The next document to write is the first one that's missing or incomplete.
33
33
 
34
- 2. **If starting fresh**, create the plan folder and start with research. Explore the problem space — read code, search the web, check Context7 for library docs. **Query the code graph** (`analyze_code_relationships`, `find_code`, `get_repository_stats`) to understand the structural landscape before scoping. Document what you find. The research doc records findings and analysis, but saves the recommendation for the brief.
34
+ 2. **If starting fresh**, create the plan folder and start with research. Explore the problem space — read code, search the web, check Context7 for library docs. **REQUIRED: Query the code graph before scoping:**
35
+ - Call `query_dependencies` on the target area to understand what depends on it and what it depends on
36
+ - Call `find_code` to find existing implementations you might reuse or need to modify
37
+ - Call `get_repository_stats` to understand the size of the area you're about to scope
38
+ - Include the graph findings in research.md — concrete numbers like "X has 12 dependents across 3 apps"
39
+ Document what you find. The research doc records findings and analysis, but saves the recommendation for the brief.
35
40
 
36
41
  3. **If research is done**, write the brief. This is where a direction emerges from the research. The brief proposes what we're building and why, informed by what the research uncovered. Present for review.
37
42
 
@@ -40,7 +40,16 @@ Key sections to fill in honestly:
40
40
  - **What We'd Do Differently** — hindsight decisions
41
41
  - **Insights Worth Carrying Forward** — takeaways for future plans
42
42
 
43
- ### Step 2: Docs Audit
43
+ ### Step 2: Structural Audit (Code Graph)
44
+
45
+ **REQUIRED:** Before reviewing docs or tests, query the code graph to understand what actually changed:
46
+
47
+ 1. Call `query_dependencies` on the key files from this plan — verify the dependency relationships match what was designed
48
+ 2. Call `find_most_complex_functions` — check if the plan introduced high-complexity code that should be refactored
49
+ 3. Call `find_dead_code` — check if the plan left behind unused functions from refactoring
50
+ 4. Include findings in the retrospective under "What Actually Happened" — e.g., "Plan touched 8 files with 23 downstream dependents"
51
+
52
+ ### Step 3: Docs Audit
44
53
 
45
54
  Review every documentation page that was written or updated during this plan's impl phases.
46
55
 
@@ -52,7 +61,7 @@ For each page:
52
61
 
53
62
  Fix any discrepancies found. Plans often diverge from their impl during execution — the docs must reflect reality.
54
63
 
55
- ### Step 3: Test Audit
64
+ ### Step 4: Test Audit
56
65
 
57
66
  Review the test files created or modified during this plan.
58
67
 
@@ -62,7 +71,7 @@ Review the test files created or modified during this plan.
62
71
 
63
72
  Flag gaps but don't necessarily fix them all now — add them as items to a follow-up plan if they're significant.
64
73
 
65
- ### Step 4: Quality Audit
74
+ ### Step 5: Quality Audit
66
75
 
67
76
  Review mistakes made during this plan's implementation.
68
77
 
@@ -72,7 +81,7 @@ Review mistakes made during this plan's implementation.
72
81
 
73
82
  The quality ratchet only gets tighter. Every retrospective is an opportunity to prevent the same class of mistake from happening again.
74
83
 
75
- ### Step 5: Context Audit
84
+ ### Step 6: Context Audit
76
85
 
77
86
  Re-read CLAUDE.md in full. After the entire impl is done, verify:
78
87
 
@@ -84,7 +93,7 @@ Re-read CLAUDE.md in full. After the entire impl is done, verify:
84
93
 
85
94
  Fix any inaccuracies. The impl may have changed things that weren't anticipated in the per-phase context updates.
86
95
 
87
- ### Step 6: Knowledge Handoff
96
+ ### Step 7: Knowledge Handoff
88
97
 
89
98
  Distill planning artifacts into the docs site so the knowledge survives archival.
90
99
 
@@ -103,7 +112,7 @@ Not every plan produces a lessons page — only create one if the insights are g
103
112
 
104
113
  **Update sidebar:** Add new decision/lesson pages to the VitePress sidebar config in `apps/indusk-docs/src/.vitepress/config.ts`.
105
114
 
106
- ### Step 7: Archival
115
+ ### Step 8: Archival
107
116
 
108
117
  Move the planning artifacts to the archive:
109
118
 
@@ -57,24 +57,46 @@ These come from the codegraphcontext MCP server:
57
57
  | Check for dead code | `find_dead_code` |
58
58
  | Scope a plan during research | `analyze_code_relationships` on the target area |
59
59
  | Custom graph queries | `execute_cypher_query` |
60
+ | Visualize the graph | `visualize_graph_query` — returns a browser link to view the graph |
61
+ | Get repo stats | `get_repository_stats` |
62
+ | See what's indexed | `list_indexed_repositories` |
63
+
64
+ ### Visualizing the Code Graph
65
+
66
+ When the user asks to "show the graph", "display dependencies", or "visualize":
67
+
68
+ 1. Call `visualize_graph_query` with a Cypher query like `MATCH (n)-[r]->(m) RETURN n, r, m LIMIT 100` — this returns a URL to open in the browser.
69
+ 2. For a specific file's dependencies: `MATCH (n)-[r]->(m) WHERE n.name CONTAINS 'filename' RETURN n, r, m`
70
+ 3. For the full project overview: `MATCH (n) RETURN n LIMIT 200`
71
+
72
+ If the user wants text-based output instead, use `execute_cypher_query` directly and format the results as a table or list.
60
73
 
61
74
  ## Tool Reference
62
75
 
63
- ### indusk (14 tools)
76
+ ### indusk (17 tools)
64
77
 
65
78
  | Tool | When to use |
66
79
  |------|-------------|
80
+ | **Graph (use these constantly)** | |
81
+ | `index_project` | After init, or when codebase changed significantly |
82
+ | `query_dependencies` | **BEFORE modifying any file** — understand blast radius |
83
+ | `query_graph` | Custom Cypher queries for advanced structural analysis |
84
+ | **Plans** | |
67
85
  | `list_plans` | Session start, orientation |
68
86
  | `get_plan_status` | Before working on a plan, checking progress |
69
87
  | `advance_plan` | End of every phase — validates all gates |
70
88
  | `order_plans` | Understanding plan dependencies |
89
+ | **Context** | |
71
90
  | `get_context` | Session start, after context updates |
72
91
  | `update_context` | Updating CLAUDE.md sections programmatically |
92
+ | **Quality** | |
73
93
  | `get_quality_config` | Reviewing Biome rules, after retros |
74
94
  | `suggest_rule` | Finding Biome rules for new patterns |
75
95
  | `quality_check` | After verification items, before advancing |
96
+ | **Docs** | |
76
97
  | `list_docs` | After document items, checking coverage |
77
98
  | `check_docs_coverage` | After retros, finding doc gaps |
99
+ | **System** | |
78
100
  | `get_system_version` | Debugging, version checks |
79
101
  | `get_skill_versions` | Checking for outdated skills |
80
102
  | `check_health` | Session start, debugging connectivity |
package/skills/verify.md CHANGED
@@ -56,7 +56,7 @@ When the work skill is executing an impl and reaches verification items, run che
56
56
  - Skip for: markdown changes, config-only changes with no test files
57
57
  - Catches: behavioral regressions, broken logic
58
58
  - Run affected app's tests, not the full suite
59
- - **Use the code graph to find affected tests** — query `analyze_code_relationships` for the changed file to discover which test files import or depend on it. Run those tests specifically rather than guessing.
59
+ - **REQUIRED: Use the code graph to find affected tests** — call `query_dependencies` on the changed file with direction "dependents" to discover which test files import or depend on it. Run those tests specifically rather than guessing. Do not skip this step.
60
60
 
61
61
  4. **Build** — `pnpm turbo build --filter={app}`
62
62
  - Only for: shared package changes, build config changes
package/skills/work.md CHANGED
@@ -25,12 +25,12 @@ Implementation plans live in `planning/{plan-name}/impl.md` as checklists. Your
25
25
  5. **Work through the checklist in order.**
26
26
  - Start from the first unchecked item (`- [ ]`)
27
27
  - For each item:
28
- a. **Query the code graph first** — before modifying a file, use `analyze_code_relationships` or `find_code` to understand its dependents. If the file is widely imported, flag the blast radius before proceeding.
29
- b. **Check for existing code** — before writing new functions, use `find_code` to search for functions that already do what you need. Reuse and extend existing code rather than duplicating. Stay DRY.
28
+ a. **REQUIRED: Query the code graph** — before modifying ANY file, call `query_dependencies` on that file. Review the dependents list. If >3 dependents, flag the blast radius to the user before proceeding. This is not optional.
29
+ b. **REQUIRED: Check for existing code** — before writing new functions, call `find_code` to search for functions that already do what you need. Reuse and extend existing code rather than duplicating. Stay DRY.
30
30
  c. Read the relevant source files
31
31
  d. Implement the change
32
- d. Immediately edit impl.md to check the item off (`- [ ]` → `- [x]`)
33
- e. Move to the next item
32
+ e. Immediately edit impl.md to check the item off (`- [ ]` → `- [x]`)
33
+ f. Move to the next item
34
34
  - Do NOT skip ahead or work out of order unless there's a dependency reason
35
35
  - Do NOT batch checklist updates — check each off as soon as it's done
36
36