gitnexus 1.1.8 → 1.2.0
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.
- package/README.md +50 -59
- package/dist/cli/ai-context.js +9 -9
- package/dist/cli/analyze.js +139 -47
- package/dist/cli/augment.d.ts +13 -0
- package/dist/cli/augment.js +33 -0
- package/dist/cli/claude-hooks.d.ts +22 -0
- package/dist/cli/claude-hooks.js +97 -0
- package/dist/cli/eval-server.d.ts +30 -0
- package/dist/cli/eval-server.js +372 -0
- package/dist/cli/index.js +56 -1
- package/dist/cli/mcp.js +9 -0
- package/dist/cli/setup.js +184 -5
- package/dist/cli/tool.d.ts +37 -0
- package/dist/cli/tool.js +91 -0
- package/dist/cli/wiki.d.ts +13 -0
- package/dist/cli/wiki.js +199 -0
- package/dist/core/augmentation/engine.d.ts +26 -0
- package/dist/core/augmentation/engine.js +213 -0
- package/dist/core/embeddings/embedder.d.ts +2 -2
- package/dist/core/embeddings/embedder.js +11 -11
- package/dist/core/embeddings/embedding-pipeline.d.ts +2 -1
- package/dist/core/embeddings/embedding-pipeline.js +13 -5
- package/dist/core/embeddings/types.d.ts +2 -2
- package/dist/core/ingestion/call-processor.d.ts +7 -0
- package/dist/core/ingestion/call-processor.js +61 -23
- package/dist/core/ingestion/community-processor.js +34 -26
- package/dist/core/ingestion/filesystem-walker.js +15 -10
- package/dist/core/ingestion/heritage-processor.d.ts +6 -0
- package/dist/core/ingestion/heritage-processor.js +68 -5
- package/dist/core/ingestion/import-processor.d.ts +22 -0
- package/dist/core/ingestion/import-processor.js +215 -20
- package/dist/core/ingestion/parsing-processor.d.ts +8 -1
- package/dist/core/ingestion/parsing-processor.js +66 -25
- package/dist/core/ingestion/pipeline.js +104 -40
- package/dist/core/ingestion/process-processor.js +1 -1
- package/dist/core/ingestion/workers/parse-worker.d.ts +58 -0
- package/dist/core/ingestion/workers/parse-worker.js +451 -0
- package/dist/core/ingestion/workers/worker-pool.d.ts +22 -0
- package/dist/core/ingestion/workers/worker-pool.js +65 -0
- package/dist/core/kuzu/kuzu-adapter.d.ts +15 -1
- package/dist/core/kuzu/kuzu-adapter.js +177 -63
- package/dist/core/kuzu/schema.d.ts +1 -1
- package/dist/core/kuzu/schema.js +3 -0
- package/dist/core/search/bm25-index.js +13 -15
- package/dist/core/wiki/generator.d.ts +96 -0
- package/dist/core/wiki/generator.js +674 -0
- package/dist/core/wiki/graph-queries.d.ts +80 -0
- package/dist/core/wiki/graph-queries.js +238 -0
- package/dist/core/wiki/html-viewer.d.ts +10 -0
- package/dist/core/wiki/html-viewer.js +297 -0
- package/dist/core/wiki/llm-client.d.ts +36 -0
- package/dist/core/wiki/llm-client.js +111 -0
- package/dist/core/wiki/prompts.d.ts +53 -0
- package/dist/core/wiki/prompts.js +174 -0
- package/dist/mcp/core/embedder.js +4 -2
- package/dist/mcp/core/kuzu-adapter.d.ts +2 -1
- package/dist/mcp/core/kuzu-adapter.js +35 -15
- package/dist/mcp/local/local-backend.d.ts +54 -1
- package/dist/mcp/local/local-backend.js +716 -171
- package/dist/mcp/resources.d.ts +1 -1
- package/dist/mcp/resources.js +111 -73
- package/dist/mcp/server.d.ts +1 -1
- package/dist/mcp/server.js +91 -22
- package/dist/mcp/tools.js +80 -61
- package/dist/storage/git.d.ts +0 -1
- package/dist/storage/git.js +1 -8
- package/dist/storage/repo-manager.d.ts +17 -0
- package/dist/storage/repo-manager.js +26 -0
- package/hooks/claude/gitnexus-hook.cjs +135 -0
- package/hooks/claude/pre-tool-use.sh +78 -0
- package/hooks/claude/session-start.sh +42 -0
- package/package.json +4 -2
- package/skills/debugging.md +24 -22
- package/skills/exploring.md +26 -24
- package/skills/impact-analysis.md +19 -13
- package/skills/refactoring.md +37 -26
package/dist/mcp/resources.d.ts
CHANGED
|
@@ -20,7 +20,7 @@ export interface ResourceTemplate {
|
|
|
20
20
|
/**
|
|
21
21
|
* Static resources — includes per-repo resources and the global repos list
|
|
22
22
|
*/
|
|
23
|
-
export declare function getResourceDefinitions(
|
|
23
|
+
export declare function getResourceDefinitions(): ResourceDefinition[];
|
|
24
24
|
/**
|
|
25
25
|
* Dynamic resource templates
|
|
26
26
|
*/
|
package/dist/mcp/resources.js
CHANGED
|
@@ -8,54 +8,55 @@ import { checkStaleness } from './staleness.js';
|
|
|
8
8
|
/**
|
|
9
9
|
* Static resources — includes per-repo resources and the global repos list
|
|
10
10
|
*/
|
|
11
|
-
export function getResourceDefinitions(
|
|
12
|
-
|
|
11
|
+
export function getResourceDefinitions() {
|
|
12
|
+
return [
|
|
13
13
|
{
|
|
14
14
|
uri: 'gitnexus://repos',
|
|
15
15
|
name: 'All Indexed Repositories',
|
|
16
16
|
description: 'List of all indexed repos with stats. Read this first to discover available repos.',
|
|
17
17
|
mimeType: 'text/yaml',
|
|
18
18
|
},
|
|
19
|
+
{
|
|
20
|
+
uri: 'gitnexus://setup',
|
|
21
|
+
name: 'GitNexus Setup Content',
|
|
22
|
+
description: 'Returns AGENTS.md content for all indexed repos. Useful for setup/onboarding.',
|
|
23
|
+
mimeType: 'text/markdown',
|
|
24
|
+
},
|
|
19
25
|
];
|
|
20
|
-
// Add per-repo context resources
|
|
21
|
-
const repos = backend.listRepos();
|
|
22
|
-
for (const repo of repos) {
|
|
23
|
-
resources.push({
|
|
24
|
-
uri: `gitnexus://repo/${repo.name}/context`,
|
|
25
|
-
name: `${repo.name} Overview`,
|
|
26
|
-
description: `Codebase stats and available tools for ${repo.name}`,
|
|
27
|
-
mimeType: 'text/yaml',
|
|
28
|
-
});
|
|
29
|
-
resources.push({
|
|
30
|
-
uri: `gitnexus://repo/${repo.name}/clusters`,
|
|
31
|
-
name: `${repo.name} Clusters`,
|
|
32
|
-
description: `All functional clusters for ${repo.name}`,
|
|
33
|
-
mimeType: 'text/yaml',
|
|
34
|
-
});
|
|
35
|
-
resources.push({
|
|
36
|
-
uri: `gitnexus://repo/${repo.name}/processes`,
|
|
37
|
-
name: `${repo.name} Processes`,
|
|
38
|
-
description: `All execution flows for ${repo.name}`,
|
|
39
|
-
mimeType: 'text/yaml',
|
|
40
|
-
});
|
|
41
|
-
resources.push({
|
|
42
|
-
uri: `gitnexus://repo/${repo.name}/schema`,
|
|
43
|
-
name: `${repo.name} Schema`,
|
|
44
|
-
description: `Graph schema for Cypher queries on ${repo.name}`,
|
|
45
|
-
mimeType: 'text/yaml',
|
|
46
|
-
});
|
|
47
|
-
}
|
|
48
|
-
return resources;
|
|
49
26
|
}
|
|
50
27
|
/**
|
|
51
28
|
* Dynamic resource templates
|
|
52
29
|
*/
|
|
53
30
|
export function getResourceTemplates() {
|
|
54
31
|
return [
|
|
32
|
+
{
|
|
33
|
+
uriTemplate: 'gitnexus://repo/{name}/context',
|
|
34
|
+
name: 'Repo Overview',
|
|
35
|
+
description: 'Codebase stats, staleness check, and available tools',
|
|
36
|
+
mimeType: 'text/yaml',
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
uriTemplate: 'gitnexus://repo/{name}/clusters',
|
|
40
|
+
name: 'Repo Modules',
|
|
41
|
+
description: 'All functional areas (Leiden clusters)',
|
|
42
|
+
mimeType: 'text/yaml',
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
uriTemplate: 'gitnexus://repo/{name}/processes',
|
|
46
|
+
name: 'Repo Processes',
|
|
47
|
+
description: 'All execution flows',
|
|
48
|
+
mimeType: 'text/yaml',
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
uriTemplate: 'gitnexus://repo/{name}/schema',
|
|
52
|
+
name: 'Graph Schema',
|
|
53
|
+
description: 'Node/edge schema for Cypher queries',
|
|
54
|
+
mimeType: 'text/yaml',
|
|
55
|
+
},
|
|
55
56
|
{
|
|
56
57
|
uriTemplate: 'gitnexus://repo/{name}/cluster/{clusterName}',
|
|
57
|
-
name: '
|
|
58
|
-
description: 'Deep dive into a specific
|
|
58
|
+
name: 'Module Detail',
|
|
59
|
+
description: 'Deep dive into a specific functional area',
|
|
59
60
|
mimeType: 'text/yaml',
|
|
60
61
|
},
|
|
61
62
|
{
|
|
@@ -72,6 +73,8 @@ export function getResourceTemplates() {
|
|
|
72
73
|
function parseUri(uri) {
|
|
73
74
|
if (uri === 'gitnexus://repos')
|
|
74
75
|
return { resourceType: 'repos' };
|
|
76
|
+
if (uri === 'gitnexus://setup')
|
|
77
|
+
return { resourceType: 'setup' };
|
|
75
78
|
// Repo-scoped: gitnexus://repo/{name}/context
|
|
76
79
|
const repoMatch = uri.match(/^gitnexus:\/\/repo\/([^/]+)\/(.+)$/);
|
|
77
80
|
if (repoMatch) {
|
|
@@ -96,6 +99,10 @@ export async function readResource(uri, backend) {
|
|
|
96
99
|
if (parsed.resourceType === 'repos') {
|
|
97
100
|
return getReposResource(backend);
|
|
98
101
|
}
|
|
102
|
+
// Setup resource — returns AGENTS.md content for all repos
|
|
103
|
+
if (parsed.resourceType === 'setup') {
|
|
104
|
+
return getSetupResource(backend);
|
|
105
|
+
}
|
|
99
106
|
const repoName = parsed.repoName;
|
|
100
107
|
switch (parsed.resourceType) {
|
|
101
108
|
case 'context':
|
|
@@ -157,15 +164,6 @@ async function getContextResource(backend, repoName) {
|
|
|
157
164
|
const repoPath = repo.repoPath;
|
|
158
165
|
const lastCommit = repo.lastCommit || 'HEAD';
|
|
159
166
|
const staleness = repoPath ? checkStaleness(repoPath, lastCommit) : { isStale: false, commitsBehind: 0 };
|
|
160
|
-
// Get aggregated cluster count (matches what overview/clusters resource shows)
|
|
161
|
-
let clusterCount = context.stats.communityCount;
|
|
162
|
-
try {
|
|
163
|
-
const overview = await backend.callTool('overview', { showClusters: true, showProcesses: false, limit: 100, repo: repoName });
|
|
164
|
-
if (overview.clusters) {
|
|
165
|
-
clusterCount = overview.clusters.length;
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
catch { /* fall back to raw count */ }
|
|
169
167
|
const lines = [
|
|
170
168
|
`project: ${context.projectName}`,
|
|
171
169
|
];
|
|
@@ -177,39 +175,38 @@ async function getContextResource(backend, repoName) {
|
|
|
177
175
|
lines.push('stats:');
|
|
178
176
|
lines.push(` files: ${context.stats.fileCount}`);
|
|
179
177
|
lines.push(` symbols: ${context.stats.functionCount}`);
|
|
180
|
-
lines.push(` clusters: ${clusterCount}`);
|
|
181
178
|
lines.push(` processes: ${context.stats.processCount}`);
|
|
182
179
|
lines.push('');
|
|
183
180
|
lines.push('tools_available:');
|
|
184
|
-
lines.push(' -
|
|
185
|
-
lines.push(' -
|
|
186
|
-
lines.push(' -
|
|
187
|
-
lines.push(' -
|
|
188
|
-
lines.push(' -
|
|
181
|
+
lines.push(' - query: Process-grouped code intelligence (execution flows related to a concept)');
|
|
182
|
+
lines.push(' - context: 360-degree symbol view (categorized refs, process participation)');
|
|
183
|
+
lines.push(' - impact: Blast radius analysis (what breaks if you change a symbol)');
|
|
184
|
+
lines.push(' - detect_changes: Git-diff impact analysis (what do your changes affect)');
|
|
185
|
+
lines.push(' - rename: Multi-file coordinated rename with confidence tags');
|
|
189
186
|
lines.push(' - cypher: Raw graph queries');
|
|
187
|
+
lines.push(' - list_repos: Discover all indexed repositories');
|
|
190
188
|
lines.push('');
|
|
191
189
|
lines.push('re_index: Run `npx gitnexus analyze` in terminal if data is stale');
|
|
192
190
|
lines.push('');
|
|
193
191
|
lines.push('resources_available:');
|
|
194
192
|
lines.push(' - gitnexus://repos: All indexed repositories');
|
|
195
|
-
lines.push(` - gitnexus://repo/${context.projectName}/clusters: All
|
|
196
|
-
lines.push(` - gitnexus://repo/${context.projectName}/processes: All
|
|
197
|
-
lines.push(` - gitnexus://repo/${context.projectName}/cluster/{name}:
|
|
193
|
+
lines.push(` - gitnexus://repo/${context.projectName}/clusters: All functional areas`);
|
|
194
|
+
lines.push(` - gitnexus://repo/${context.projectName}/processes: All execution flows`);
|
|
195
|
+
lines.push(` - gitnexus://repo/${context.projectName}/cluster/{name}: Module details`);
|
|
198
196
|
lines.push(` - gitnexus://repo/${context.projectName}/process/{name}: Process trace`);
|
|
199
197
|
return lines.join('\n');
|
|
200
198
|
}
|
|
201
199
|
/**
|
|
202
|
-
* Clusters resource
|
|
200
|
+
* Clusters resource — queries graph directly via backend.queryClusters()
|
|
203
201
|
*/
|
|
204
202
|
async function getClustersResource(backend, repoName) {
|
|
205
203
|
try {
|
|
206
|
-
|
|
207
|
-
const result = await backend.callTool('overview', { showClusters: true, showProcesses: false, limit: 100, repo: repoName });
|
|
204
|
+
const result = await backend.queryClusters(repoName, 100);
|
|
208
205
|
if (!result.clusters || result.clusters.length === 0) {
|
|
209
|
-
return '
|
|
206
|
+
return 'modules: []\n# No functional areas detected. Run: gitnexus analyze';
|
|
210
207
|
}
|
|
211
208
|
const displayLimit = 20;
|
|
212
|
-
const lines = ['
|
|
209
|
+
const lines = ['modules:'];
|
|
213
210
|
const toShow = result.clusters.slice(0, displayLimit);
|
|
214
211
|
for (const cluster of toShow) {
|
|
215
212
|
const label = cluster.heuristicLabel || cluster.label || cluster.id;
|
|
@@ -218,12 +215,9 @@ async function getClustersResource(backend, repoName) {
|
|
|
218
215
|
if (cluster.cohesion) {
|
|
219
216
|
lines.push(` cohesion: ${(cluster.cohesion * 100).toFixed(0)}%`);
|
|
220
217
|
}
|
|
221
|
-
if (cluster.subCommunities && cluster.subCommunities > 1) {
|
|
222
|
-
lines.push(` sub_clusters: ${cluster.subCommunities}`);
|
|
223
|
-
}
|
|
224
218
|
}
|
|
225
219
|
if (result.clusters.length > displayLimit) {
|
|
226
|
-
lines.push(`\n# Showing top ${displayLimit} of ${result.clusters.length}
|
|
220
|
+
lines.push(`\n# Showing top ${displayLimit} of ${result.clusters.length} modules. Use gitnexus_query for deeper search.`);
|
|
227
221
|
}
|
|
228
222
|
return lines.join('\n');
|
|
229
223
|
}
|
|
@@ -232,11 +226,11 @@ async function getClustersResource(backend, repoName) {
|
|
|
232
226
|
}
|
|
233
227
|
}
|
|
234
228
|
/**
|
|
235
|
-
* Processes resource
|
|
229
|
+
* Processes resource — queries graph directly via backend.queryProcesses()
|
|
236
230
|
*/
|
|
237
231
|
async function getProcessesResource(backend, repoName) {
|
|
238
232
|
try {
|
|
239
|
-
const result = await backend.
|
|
233
|
+
const result = await backend.queryProcesses(repoName, 50);
|
|
240
234
|
if (!result.processes || result.processes.length === 0) {
|
|
241
235
|
return 'processes: []\n# No processes detected. Run: gitnexus analyze';
|
|
242
236
|
}
|
|
@@ -250,7 +244,7 @@ async function getProcessesResource(backend, repoName) {
|
|
|
250
244
|
lines.push(` steps: ${proc.stepCount || 0}`);
|
|
251
245
|
}
|
|
252
246
|
if (result.processes.length > displayLimit) {
|
|
253
|
-
lines.push(`\n# Showing top ${displayLimit} of ${result.processes.length} processes. Use
|
|
247
|
+
lines.push(`\n# Showing top ${displayLimit} of ${result.processes.length} processes. Use gitnexus_query for deeper search.`);
|
|
254
248
|
}
|
|
255
249
|
return lines.join('\n');
|
|
256
250
|
}
|
|
@@ -266,22 +260,29 @@ function getSchemaResource() {
|
|
|
266
260
|
|
|
267
261
|
nodes:
|
|
268
262
|
- File: Source code files
|
|
263
|
+
- Folder: Directory containers
|
|
269
264
|
- Function: Functions and arrow functions
|
|
270
265
|
- Class: Class definitions
|
|
271
266
|
- Interface: Interface/type definitions
|
|
272
267
|
- Method: Class methods
|
|
273
|
-
-
|
|
268
|
+
- CodeElement: Catch-all for other code elements
|
|
269
|
+
- Community: Auto-detected functional area (Leiden algorithm)
|
|
274
270
|
- Process: Execution flow trace
|
|
275
271
|
|
|
272
|
+
additional_node_types: "Multi-language: Struct, Enum, Macro, Typedef, Union, Namespace, Trait, Impl, TypeAlias, Const, Static, Property, Record, Delegate, Annotation, Constructor, Template, Module (use backticks in queries: \`Struct\`, \`Enum\`, etc.)"
|
|
273
|
+
|
|
276
274
|
relationships:
|
|
275
|
+
- CONTAINS: File/Folder contains child
|
|
276
|
+
- DEFINES: File defines a symbol
|
|
277
277
|
- CALLS: Function/method invocation
|
|
278
278
|
- IMPORTS: Module imports
|
|
279
279
|
- EXTENDS: Class inheritance
|
|
280
280
|
- IMPLEMENTS: Interface implementation
|
|
281
|
-
- DEFINES: File defines symbol
|
|
282
281
|
- MEMBER_OF: Symbol belongs to community
|
|
283
282
|
- STEP_IN_PROCESS: Symbol is step N in process
|
|
284
283
|
|
|
284
|
+
relationship_table: "All relationships use a single CodeRelation table with a 'type' property. Properties: type (STRING), confidence (DOUBLE), reason (STRING), step (INT32)"
|
|
285
|
+
|
|
285
286
|
example_queries:
|
|
286
287
|
find_callers: |
|
|
287
288
|
MATCH (caller)-[:CodeRelation {type: 'CALLS'}]->(f:Function {name: "myFunc"})
|
|
@@ -300,26 +301,23 @@ example_queries:
|
|
|
300
301
|
`;
|
|
301
302
|
}
|
|
302
303
|
/**
|
|
303
|
-
* Cluster detail resource
|
|
304
|
+
* Cluster detail resource — queries graph directly via backend.queryClusterDetail()
|
|
304
305
|
*/
|
|
305
306
|
async function getClusterDetailResource(name, backend, repoName) {
|
|
306
307
|
try {
|
|
307
|
-
const result = await backend.
|
|
308
|
+
const result = await backend.queryClusterDetail(name, repoName);
|
|
308
309
|
if (result.error) {
|
|
309
310
|
return `error: ${result.error}`;
|
|
310
311
|
}
|
|
311
312
|
const cluster = result.cluster;
|
|
312
313
|
const members = result.members || [];
|
|
313
314
|
const lines = [
|
|
314
|
-
`
|
|
315
|
+
`module: "${cluster.heuristicLabel || cluster.label || cluster.id}"`,
|
|
315
316
|
`symbols: ${cluster.symbolCount || members.length}`,
|
|
316
317
|
];
|
|
317
318
|
if (cluster.cohesion) {
|
|
318
319
|
lines.push(`cohesion: ${(cluster.cohesion * 100).toFixed(0)}%`);
|
|
319
320
|
}
|
|
320
|
-
if (cluster.subCommunities && cluster.subCommunities > 1) {
|
|
321
|
-
lines.push(`sub_clusters: ${cluster.subCommunities}`);
|
|
322
|
-
}
|
|
323
321
|
if (members.length > 0) {
|
|
324
322
|
lines.push('');
|
|
325
323
|
lines.push('members:');
|
|
@@ -339,11 +337,11 @@ async function getClusterDetailResource(name, backend, repoName) {
|
|
|
339
337
|
}
|
|
340
338
|
}
|
|
341
339
|
/**
|
|
342
|
-
* Process detail resource
|
|
340
|
+
* Process detail resource — queries graph directly via backend.queryProcessDetail()
|
|
343
341
|
*/
|
|
344
342
|
async function getProcessDetailResource(name, backend, repoName) {
|
|
345
343
|
try {
|
|
346
|
-
const result = await backend.
|
|
344
|
+
const result = await backend.queryProcessDetail(name, repoName);
|
|
347
345
|
if (result.error) {
|
|
348
346
|
return `error: ${result.error}`;
|
|
349
347
|
}
|
|
@@ -367,3 +365,43 @@ async function getProcessDetailResource(name, backend, repoName) {
|
|
|
367
365
|
return `error: ${err.message}`;
|
|
368
366
|
}
|
|
369
367
|
}
|
|
368
|
+
/**
|
|
369
|
+
* Setup resource — generates AGENTS.md content for all indexed repos.
|
|
370
|
+
* Useful for `gitnexus setup` onboarding or dynamic content injection.
|
|
371
|
+
*/
|
|
372
|
+
async function getSetupResource(backend) {
|
|
373
|
+
const repos = backend.listRepos();
|
|
374
|
+
if (repos.length === 0) {
|
|
375
|
+
return '# GitNexus\n\nNo repositories indexed. Run: `npx gitnexus analyze` in a repository.';
|
|
376
|
+
}
|
|
377
|
+
const sections = [];
|
|
378
|
+
for (const repo of repos) {
|
|
379
|
+
const stats = repo.stats || {};
|
|
380
|
+
const lines = [
|
|
381
|
+
`# GitNexus MCP — ${repo.name}`,
|
|
382
|
+
'',
|
|
383
|
+
`This project is indexed by GitNexus as **${repo.name}** (${stats.nodes || 0} symbols, ${stats.edges || 0} relationships, ${stats.processes || 0} execution flows).`,
|
|
384
|
+
'',
|
|
385
|
+
'## Tools',
|
|
386
|
+
'',
|
|
387
|
+
'| Tool | What it gives you |',
|
|
388
|
+
'|------|-------------------|',
|
|
389
|
+
'| `query` | Process-grouped code intelligence — execution flows related to a concept |',
|
|
390
|
+
'| `context` | 360-degree symbol view — categorized refs, processes it participates in |',
|
|
391
|
+
'| `impact` | Symbol blast radius — what breaks at depth 1/2/3 with confidence |',
|
|
392
|
+
'| `detect_changes` | Git-diff impact — what do your current changes affect |',
|
|
393
|
+
'| `rename` | Multi-file coordinated rename with confidence-tagged edits |',
|
|
394
|
+
'| `cypher` | Raw graph queries |',
|
|
395
|
+
'| `list_repos` | Discover indexed repos |',
|
|
396
|
+
'',
|
|
397
|
+
'## Resources',
|
|
398
|
+
'',
|
|
399
|
+
`- \`gitnexus://repo/${repo.name}/context\` — Stats, staleness check`,
|
|
400
|
+
`- \`gitnexus://repo/${repo.name}/clusters\` — All functional areas`,
|
|
401
|
+
`- \`gitnexus://repo/${repo.name}/processes\` — All execution flows`,
|
|
402
|
+
`- \`gitnexus://repo/${repo.name}/schema\` — Graph schema for Cypher`,
|
|
403
|
+
];
|
|
404
|
+
sections.push(lines.join('\n'));
|
|
405
|
+
}
|
|
406
|
+
return sections.join('\n\n---\n\n');
|
|
407
|
+
}
|
package/dist/mcp/server.d.ts
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
*
|
|
8
8
|
* Supports multiple indexed repositories via the global registry.
|
|
9
9
|
*
|
|
10
|
-
* Tools: list_repos,
|
|
10
|
+
* Tools: list_repos, query, cypher, context, impact, detect_changes, rename
|
|
11
11
|
* Resources: repos, repo/{name}/context, repo/{name}/clusters, ...
|
|
12
12
|
*/
|
|
13
13
|
import type { LocalBackend } from './local/local-backend.js';
|
package/dist/mcp/server.js
CHANGED
|
@@ -7,12 +7,12 @@
|
|
|
7
7
|
*
|
|
8
8
|
* Supports multiple indexed repositories via the global registry.
|
|
9
9
|
*
|
|
10
|
-
* Tools: list_repos,
|
|
10
|
+
* Tools: list_repos, query, cypher, context, impact, detect_changes, rename
|
|
11
11
|
* Resources: repos, repo/{name}/context, repo/{name}/clusters, ...
|
|
12
12
|
*/
|
|
13
13
|
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
14
14
|
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
15
|
-
import { CallToolRequestSchema, ListToolsRequestSchema, ListResourcesRequestSchema, ReadResourceRequestSchema, ListResourceTemplatesRequestSchema, } from '@modelcontextprotocol/sdk/types.js';
|
|
15
|
+
import { CallToolRequestSchema, ListToolsRequestSchema, ListResourcesRequestSchema, ReadResourceRequestSchema, ListResourceTemplatesRequestSchema, ListPromptsRequestSchema, GetPromptRequestSchema, } from '@modelcontextprotocol/sdk/types.js';
|
|
16
16
|
import { GITNEXUS_TOOLS } from './tools.js';
|
|
17
17
|
import { getResourceDefinitions, getResourceTemplates, readResource } from './resources.js';
|
|
18
18
|
/**
|
|
@@ -31,27 +31,25 @@ function getNextStepHint(toolName, args) {
|
|
|
31
31
|
switch (toolName) {
|
|
32
32
|
case 'list_repos':
|
|
33
33
|
return `\n\n---\n**Next:** READ gitnexus://repo/{name}/context for any repo above to get its overview and check staleness.`;
|
|
34
|
-
case '
|
|
35
|
-
return `\n\n---\n**Next:** To understand a
|
|
36
|
-
case '
|
|
37
|
-
|
|
38
|
-
if (exploreType === 'symbol') {
|
|
39
|
-
return `\n\n---\n**Next:** If planning changes, use impact({target: "${args?.name || '<name>'}", direction: "upstream"${repoParam}}) to check blast radius. To see execution flows, READ gitnexus://repo/${repoPath}/processes.`;
|
|
40
|
-
}
|
|
41
|
-
if (exploreType === 'cluster') {
|
|
42
|
-
return `\n\n---\n**Next:** To drill into a specific symbol, use explore({name: "<symbol_name>", type: "symbol"${repoParam}}). To see execution flows, READ gitnexus://repo/${repoPath}/processes.`;
|
|
43
|
-
}
|
|
44
|
-
if (exploreType === 'process') {
|
|
45
|
-
return `\n\n---\n**Next:** To explore any step in detail, use explore({name: "<step_name>", type: "symbol"${repoParam}}).`;
|
|
46
|
-
}
|
|
47
|
-
return '';
|
|
48
|
-
}
|
|
49
|
-
case 'overview':
|
|
50
|
-
return `\n\n---\n**Next:** To drill into a cluster, READ gitnexus://repo/${repoPath}/cluster/{name} or use explore({name: "<cluster_name>", type: "cluster"${repoParam}}).`;
|
|
34
|
+
case 'query':
|
|
35
|
+
return `\n\n---\n**Next:** To understand a specific symbol in depth, use context({name: "<symbol_name>"${repoParam}}) to see categorized refs and process participation.`;
|
|
36
|
+
case 'context':
|
|
37
|
+
return `\n\n---\n**Next:** If planning changes, use impact({target: "${args?.name || '<name>'}", direction: "upstream"${repoParam}}) to check blast radius. To see execution flows, READ gitnexus://repo/${repoPath}/processes.`;
|
|
51
38
|
case 'impact':
|
|
52
39
|
return `\n\n---\n**Next:** Review d=1 items first (WILL BREAK). To check affected execution flows, READ gitnexus://repo/${repoPath}/processes.`;
|
|
40
|
+
case 'detect_changes':
|
|
41
|
+
return `\n\n---\n**Next:** Review affected processes. Use context() on high-risk changed symbols. READ gitnexus://repo/${repoPath}/process/{name} for full execution traces.`;
|
|
42
|
+
case 'rename':
|
|
43
|
+
return `\n\n---\n**Next:** Run detect_changes(${repoParam ? `{repo: "${repo}"}` : ''}) to verify no unexpected side effects from the rename.`;
|
|
53
44
|
case 'cypher':
|
|
54
|
-
return `\n\n---\n**Next:** To explore a result symbol, use
|
|
45
|
+
return `\n\n---\n**Next:** To explore a result symbol, use context({name: "<name>"${repoParam}}). For schema reference, READ gitnexus://repo/${repoPath}/schema.`;
|
|
46
|
+
// Legacy tool names — still return useful hints
|
|
47
|
+
case 'search':
|
|
48
|
+
return `\n\n---\n**Next:** To understand a result in context, use context({name: "<symbol_name>"${repoParam}}).`;
|
|
49
|
+
case 'explore':
|
|
50
|
+
return `\n\n---\n**Next:** If planning changes, use impact({target: "<name>", direction: "upstream"${repoParam}}).`;
|
|
51
|
+
case 'overview':
|
|
52
|
+
return `\n\n---\n**Next:** To drill into an area, READ gitnexus://repo/${repoPath}/cluster/{name}. To see execution flows, READ gitnexus://repo/${repoPath}/processes.`;
|
|
55
53
|
default:
|
|
56
54
|
return '';
|
|
57
55
|
}
|
|
@@ -59,16 +57,17 @@ function getNextStepHint(toolName, args) {
|
|
|
59
57
|
export async function startMCPServer(backend) {
|
|
60
58
|
const server = new Server({
|
|
61
59
|
name: 'gitnexus',
|
|
62
|
-
version: '1.1.
|
|
60
|
+
version: '1.1.9',
|
|
63
61
|
}, {
|
|
64
62
|
capabilities: {
|
|
65
63
|
tools: {},
|
|
66
64
|
resources: {},
|
|
65
|
+
prompts: {},
|
|
67
66
|
},
|
|
68
67
|
});
|
|
69
68
|
// Handle list resources request
|
|
70
69
|
server.setRequestHandler(ListResourcesRequestSchema, async () => {
|
|
71
|
-
const resources = getResourceDefinitions(
|
|
70
|
+
const resources = getResourceDefinitions();
|
|
72
71
|
return {
|
|
73
72
|
resources: resources.map(r => ({
|
|
74
73
|
uri: r.uri,
|
|
@@ -154,6 +153,76 @@ export async function startMCPServer(backend) {
|
|
|
154
153
|
};
|
|
155
154
|
}
|
|
156
155
|
});
|
|
156
|
+
// Handle list prompts request
|
|
157
|
+
server.setRequestHandler(ListPromptsRequestSchema, async () => ({
|
|
158
|
+
prompts: [
|
|
159
|
+
{
|
|
160
|
+
name: 'detect_impact',
|
|
161
|
+
description: 'Analyze the impact of your current changes before committing. Guides through scope selection, change detection, process analysis, and risk assessment.',
|
|
162
|
+
arguments: [
|
|
163
|
+
{ name: 'scope', description: 'What to analyze: unstaged, staged, all, or compare', required: false },
|
|
164
|
+
{ name: 'base_ref', description: 'Branch/commit for compare scope', required: false },
|
|
165
|
+
],
|
|
166
|
+
},
|
|
167
|
+
{
|
|
168
|
+
name: 'generate_map',
|
|
169
|
+
description: 'Generate architecture documentation from the knowledge graph. Creates a codebase overview with execution flows and mermaid diagrams.',
|
|
170
|
+
arguments: [
|
|
171
|
+
{ name: 'repo', description: 'Repository name (omit if only one indexed)', required: false },
|
|
172
|
+
],
|
|
173
|
+
},
|
|
174
|
+
],
|
|
175
|
+
}));
|
|
176
|
+
// Handle get prompt request
|
|
177
|
+
server.setRequestHandler(GetPromptRequestSchema, async (request) => {
|
|
178
|
+
const { name, arguments: args } = request.params;
|
|
179
|
+
if (name === 'detect_impact') {
|
|
180
|
+
const scope = args?.scope || 'all';
|
|
181
|
+
const baseRef = args?.base_ref || '';
|
|
182
|
+
return {
|
|
183
|
+
messages: [
|
|
184
|
+
{
|
|
185
|
+
role: 'user',
|
|
186
|
+
content: {
|
|
187
|
+
type: 'text',
|
|
188
|
+
text: `Analyze the impact of my current code changes before committing.
|
|
189
|
+
|
|
190
|
+
Follow these steps:
|
|
191
|
+
1. Run \`detect_changes(${JSON.stringify({ scope, ...(baseRef ? { base_ref: baseRef } : {}) })})\` to find what changed and affected processes
|
|
192
|
+
2. For each changed symbol in critical processes, run \`context({name: "<symbol>"})\` to see its full reference graph
|
|
193
|
+
3. For any high-risk items (many callers or cross-process), run \`impact({target: "<symbol>", direction: "upstream"})\` for blast radius
|
|
194
|
+
4. Summarize: changes, affected processes, risk level, and recommended actions
|
|
195
|
+
|
|
196
|
+
Present the analysis as a clear risk report.`,
|
|
197
|
+
},
|
|
198
|
+
},
|
|
199
|
+
],
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
if (name === 'generate_map') {
|
|
203
|
+
const repo = args?.repo || '';
|
|
204
|
+
return {
|
|
205
|
+
messages: [
|
|
206
|
+
{
|
|
207
|
+
role: 'user',
|
|
208
|
+
content: {
|
|
209
|
+
type: 'text',
|
|
210
|
+
text: `Generate architecture documentation for this codebase using the knowledge graph.
|
|
211
|
+
|
|
212
|
+
Follow these steps:
|
|
213
|
+
1. READ \`gitnexus://repo/${repo || '{name}'}/context\` for codebase stats
|
|
214
|
+
2. READ \`gitnexus://repo/${repo || '{name}'}/clusters\` to see all functional areas
|
|
215
|
+
3. READ \`gitnexus://repo/${repo || '{name}'}/processes\` to see all execution flows
|
|
216
|
+
4. For the top 5 most important processes, READ \`gitnexus://repo/${repo || '{name}'}/process/{name}\` for step-by-step traces
|
|
217
|
+
5. Generate a mermaid architecture diagram showing the major areas and their connections
|
|
218
|
+
6. Write an ARCHITECTURE.md file with: overview, functional areas, key execution flows, and the mermaid diagram`,
|
|
219
|
+
},
|
|
220
|
+
},
|
|
221
|
+
],
|
|
222
|
+
};
|
|
223
|
+
}
|
|
224
|
+
throw new Error(`Unknown prompt: ${name}`);
|
|
225
|
+
});
|
|
157
226
|
// Connect to stdio transport
|
|
158
227
|
const transport = new StdioServerTransport();
|
|
159
228
|
await server.connect(transport);
|