@veewo/gitnexus 1.3.4
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 +234 -0
- package/dist/benchmark/agent-context/evaluators.d.ts +9 -0
- package/dist/benchmark/agent-context/evaluators.js +196 -0
- package/dist/benchmark/agent-context/evaluators.test.d.ts +1 -0
- package/dist/benchmark/agent-context/evaluators.test.js +39 -0
- package/dist/benchmark/agent-context/io.d.ts +2 -0
- package/dist/benchmark/agent-context/io.js +23 -0
- package/dist/benchmark/agent-context/io.test.d.ts +1 -0
- package/dist/benchmark/agent-context/io.test.js +19 -0
- package/dist/benchmark/agent-context/report.d.ts +2 -0
- package/dist/benchmark/agent-context/report.js +59 -0
- package/dist/benchmark/agent-context/report.test.d.ts +1 -0
- package/dist/benchmark/agent-context/report.test.js +85 -0
- package/dist/benchmark/agent-context/runner.d.ts +46 -0
- package/dist/benchmark/agent-context/runner.js +111 -0
- package/dist/benchmark/agent-context/runner.test.d.ts +1 -0
- package/dist/benchmark/agent-context/runner.test.js +79 -0
- package/dist/benchmark/agent-context/tool-runner.d.ts +7 -0
- package/dist/benchmark/agent-context/tool-runner.js +18 -0
- package/dist/benchmark/agent-context/tool-runner.test.d.ts +1 -0
- package/dist/benchmark/agent-context/tool-runner.test.js +11 -0
- package/dist/benchmark/agent-context/types.d.ts +40 -0
- package/dist/benchmark/agent-context/types.js +1 -0
- package/dist/benchmark/analyze-runner.d.ts +16 -0
- package/dist/benchmark/analyze-runner.js +51 -0
- package/dist/benchmark/analyze-runner.test.d.ts +1 -0
- package/dist/benchmark/analyze-runner.test.js +37 -0
- package/dist/benchmark/evaluators.d.ts +6 -0
- package/dist/benchmark/evaluators.js +10 -0
- package/dist/benchmark/evaluators.test.d.ts +1 -0
- package/dist/benchmark/evaluators.test.js +12 -0
- package/dist/benchmark/io.d.ts +7 -0
- package/dist/benchmark/io.js +25 -0
- package/dist/benchmark/io.test.d.ts +1 -0
- package/dist/benchmark/io.test.js +35 -0
- package/dist/benchmark/neonspark-candidates.d.ts +19 -0
- package/dist/benchmark/neonspark-candidates.js +94 -0
- package/dist/benchmark/neonspark-candidates.test.d.ts +1 -0
- package/dist/benchmark/neonspark-candidates.test.js +43 -0
- package/dist/benchmark/neonspark-materialize.d.ts +19 -0
- package/dist/benchmark/neonspark-materialize.js +111 -0
- package/dist/benchmark/neonspark-materialize.test.d.ts +1 -0
- package/dist/benchmark/neonspark-materialize.test.js +124 -0
- package/dist/benchmark/neonspark-sync.d.ts +3 -0
- package/dist/benchmark/neonspark-sync.js +53 -0
- package/dist/benchmark/neonspark-sync.test.d.ts +1 -0
- package/dist/benchmark/neonspark-sync.test.js +20 -0
- package/dist/benchmark/report.d.ts +1 -0
- package/dist/benchmark/report.js +7 -0
- package/dist/benchmark/runner.d.ts +48 -0
- package/dist/benchmark/runner.js +302 -0
- package/dist/benchmark/runner.test.d.ts +1 -0
- package/dist/benchmark/runner.test.js +50 -0
- package/dist/benchmark/scoring.d.ts +16 -0
- package/dist/benchmark/scoring.js +27 -0
- package/dist/benchmark/scoring.test.d.ts +1 -0
- package/dist/benchmark/scoring.test.js +24 -0
- package/dist/benchmark/tool-runner.d.ts +6 -0
- package/dist/benchmark/tool-runner.js +17 -0
- package/dist/benchmark/types.d.ts +36 -0
- package/dist/benchmark/types.js +1 -0
- package/dist/cli/ai-context.d.ts +22 -0
- package/dist/cli/ai-context.js +184 -0
- package/dist/cli/ai-context.test.d.ts +1 -0
- package/dist/cli/ai-context.test.js +30 -0
- package/dist/cli/analyze-multi-scope-regression.test.d.ts +1 -0
- package/dist/cli/analyze-multi-scope-regression.test.js +22 -0
- package/dist/cli/analyze-options.d.ts +7 -0
- package/dist/cli/analyze-options.js +56 -0
- package/dist/cli/analyze-options.test.d.ts +1 -0
- package/dist/cli/analyze-options.test.js +36 -0
- package/dist/cli/analyze.d.ts +14 -0
- package/dist/cli/analyze.js +384 -0
- package/dist/cli/augment.d.ts +13 -0
- package/dist/cli/augment.js +33 -0
- package/dist/cli/benchmark-agent-context.d.ts +29 -0
- package/dist/cli/benchmark-agent-context.js +61 -0
- package/dist/cli/benchmark-agent-context.test.d.ts +1 -0
- package/dist/cli/benchmark-agent-context.test.js +80 -0
- package/dist/cli/benchmark-unity.d.ts +15 -0
- package/dist/cli/benchmark-unity.js +31 -0
- package/dist/cli/benchmark-unity.test.d.ts +1 -0
- package/dist/cli/benchmark-unity.test.js +18 -0
- package/dist/cli/claude-hooks.d.ts +22 -0
- package/dist/cli/claude-hooks.js +97 -0
- package/dist/cli/clean.d.ts +10 -0
- package/dist/cli/clean.js +60 -0
- package/dist/cli/eval-server.d.ts +30 -0
- package/dist/cli/eval-server.js +372 -0
- package/dist/cli/index.d.ts +2 -0
- package/dist/cli/index.js +182 -0
- package/dist/cli/list.d.ts +6 -0
- package/dist/cli/list.js +33 -0
- package/dist/cli/mcp.d.ts +8 -0
- package/dist/cli/mcp.js +34 -0
- package/dist/cli/repo-manager-alias.test.d.ts +1 -0
- package/dist/cli/repo-manager-alias.test.js +40 -0
- package/dist/cli/scope-filter.test.d.ts +1 -0
- package/dist/cli/scope-filter.test.js +49 -0
- package/dist/cli/serve.d.ts +4 -0
- package/dist/cli/serve.js +6 -0
- package/dist/cli/setup.d.ts +8 -0
- package/dist/cli/setup.js +311 -0
- package/dist/cli/setup.test.d.ts +1 -0
- package/dist/cli/setup.test.js +31 -0
- package/dist/cli/status.d.ts +6 -0
- package/dist/cli/status.js +27 -0
- package/dist/cli/tool.d.ts +40 -0
- package/dist/cli/tool.js +94 -0
- package/dist/cli/version.test.d.ts +1 -0
- package/dist/cli/version.test.js +19 -0
- package/dist/cli/wiki.d.ts +15 -0
- package/dist/cli/wiki.js +361 -0
- package/dist/config/ignore-service.d.ts +1 -0
- package/dist/config/ignore-service.js +210 -0
- package/dist/config/supported-languages.d.ts +12 -0
- package/dist/config/supported-languages.js +15 -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 +60 -0
- package/dist/core/embeddings/embedder.js +251 -0
- package/dist/core/embeddings/embedding-pipeline.d.ts +51 -0
- package/dist/core/embeddings/embedding-pipeline.js +329 -0
- package/dist/core/embeddings/index.d.ts +9 -0
- package/dist/core/embeddings/index.js +9 -0
- package/dist/core/embeddings/text-generator.d.ts +24 -0
- package/dist/core/embeddings/text-generator.js +182 -0
- package/dist/core/embeddings/types.d.ts +87 -0
- package/dist/core/embeddings/types.js +32 -0
- package/dist/core/graph/graph.d.ts +2 -0
- package/dist/core/graph/graph.js +66 -0
- package/dist/core/graph/types.d.ts +61 -0
- package/dist/core/graph/types.js +1 -0
- package/dist/core/ingestion/ast-cache.d.ts +11 -0
- package/dist/core/ingestion/ast-cache.js +34 -0
- package/dist/core/ingestion/call-processor.d.ts +15 -0
- package/dist/core/ingestion/call-processor.js +327 -0
- package/dist/core/ingestion/cluster-enricher.d.ts +38 -0
- package/dist/core/ingestion/cluster-enricher.js +170 -0
- package/dist/core/ingestion/community-processor.d.ts +39 -0
- package/dist/core/ingestion/community-processor.js +312 -0
- package/dist/core/ingestion/entry-point-scoring.d.ts +39 -0
- package/dist/core/ingestion/entry-point-scoring.js +260 -0
- package/dist/core/ingestion/filesystem-walker.d.ts +28 -0
- package/dist/core/ingestion/filesystem-walker.js +80 -0
- package/dist/core/ingestion/framework-detection.d.ts +39 -0
- package/dist/core/ingestion/framework-detection.js +235 -0
- package/dist/core/ingestion/heritage-processor.d.ts +20 -0
- package/dist/core/ingestion/heritage-processor.js +197 -0
- package/dist/core/ingestion/import-processor.d.ts +38 -0
- package/dist/core/ingestion/import-processor.js +778 -0
- package/dist/core/ingestion/parsing-processor.d.ts +15 -0
- package/dist/core/ingestion/parsing-processor.js +291 -0
- package/dist/core/ingestion/pipeline.d.ts +5 -0
- package/dist/core/ingestion/pipeline.js +323 -0
- package/dist/core/ingestion/process-processor.d.ts +51 -0
- package/dist/core/ingestion/process-processor.js +309 -0
- package/dist/core/ingestion/scope-filter.d.ts +25 -0
- package/dist/core/ingestion/scope-filter.js +100 -0
- package/dist/core/ingestion/structure-processor.d.ts +2 -0
- package/dist/core/ingestion/structure-processor.js +36 -0
- package/dist/core/ingestion/symbol-table.d.ts +33 -0
- package/dist/core/ingestion/symbol-table.js +38 -0
- package/dist/core/ingestion/tree-sitter-queries.d.ts +12 -0
- package/dist/core/ingestion/tree-sitter-queries.js +398 -0
- package/dist/core/ingestion/utils.d.ts +10 -0
- package/dist/core/ingestion/utils.js +50 -0
- package/dist/core/ingestion/workers/parse-worker.d.ts +59 -0
- package/dist/core/ingestion/workers/parse-worker.js +672 -0
- package/dist/core/ingestion/workers/worker-pool.d.ts +16 -0
- package/dist/core/ingestion/workers/worker-pool.js +120 -0
- package/dist/core/kuzu/csv-generator.d.ts +29 -0
- package/dist/core/kuzu/csv-generator.js +336 -0
- package/dist/core/kuzu/kuzu-adapter.d.ts +101 -0
- package/dist/core/kuzu/kuzu-adapter.js +753 -0
- package/dist/core/kuzu/schema.d.ts +53 -0
- package/dist/core/kuzu/schema.js +407 -0
- package/dist/core/search/bm25-index.d.ts +23 -0
- package/dist/core/search/bm25-index.js +95 -0
- package/dist/core/search/hybrid-search.d.ts +49 -0
- package/dist/core/search/hybrid-search.js +118 -0
- package/dist/core/tree-sitter/parser-loader.d.ts +4 -0
- package/dist/core/tree-sitter/parser-loader.js +44 -0
- package/dist/core/wiki/generator.d.ts +110 -0
- package/dist/core/wiki/generator.js +786 -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 +40 -0
- package/dist/core/wiki/llm-client.js +162 -0
- package/dist/core/wiki/prompts.d.ts +53 -0
- package/dist/core/wiki/prompts.js +174 -0
- package/dist/lib/utils.d.ts +1 -0
- package/dist/lib/utils.js +3 -0
- package/dist/mcp/core/embedder.d.ts +27 -0
- package/dist/mcp/core/embedder.js +108 -0
- package/dist/mcp/core/kuzu-adapter.d.ts +34 -0
- package/dist/mcp/core/kuzu-adapter.js +231 -0
- package/dist/mcp/local/local-backend.d.ts +160 -0
- package/dist/mcp/local/local-backend.js +1646 -0
- package/dist/mcp/resources.d.ts +31 -0
- package/dist/mcp/resources.js +407 -0
- package/dist/mcp/server.d.ts +23 -0
- package/dist/mcp/server.js +251 -0
- package/dist/mcp/staleness.d.ts +15 -0
- package/dist/mcp/staleness.js +29 -0
- package/dist/mcp/tools.d.ts +24 -0
- package/dist/mcp/tools.js +195 -0
- package/dist/server/api.d.ts +10 -0
- package/dist/server/api.js +344 -0
- package/dist/server/mcp-http.d.ts +13 -0
- package/dist/server/mcp-http.js +100 -0
- package/dist/storage/git.d.ts +6 -0
- package/dist/storage/git.js +32 -0
- package/dist/storage/repo-manager.d.ts +125 -0
- package/dist/storage/repo-manager.js +257 -0
- package/dist/types/pipeline.d.ts +34 -0
- package/dist/types/pipeline.js +18 -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 +92 -0
- package/skills/gitnexus-cli.md +82 -0
- package/skills/gitnexus-debugging.md +89 -0
- package/skills/gitnexus-exploring.md +78 -0
- package/skills/gitnexus-guide.md +64 -0
- package/skills/gitnexus-impact-analysis.md +97 -0
- package/skills/gitnexus-refactoring.md +121 -0
- package/vendor/leiden/index.cjs +355 -0
- package/vendor/leiden/utils.cjs +392 -0
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP Server (Multi-Repo)
|
|
3
|
+
*
|
|
4
|
+
* Model Context Protocol server that runs on stdio.
|
|
5
|
+
* External AI tools (Cursor, Claude) spawn this process and
|
|
6
|
+
* communicate via stdin/stdout using the MCP protocol.
|
|
7
|
+
*
|
|
8
|
+
* Supports multiple indexed repositories via the global registry.
|
|
9
|
+
*
|
|
10
|
+
* Tools: list_repos, query, cypher, context, impact, detect_changes, rename
|
|
11
|
+
* Resources: repos, repo/{name}/context, repo/{name}/clusters, ...
|
|
12
|
+
*/
|
|
13
|
+
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
14
|
+
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
15
|
+
import { CallToolRequestSchema, ListToolsRequestSchema, ListResourcesRequestSchema, ReadResourceRequestSchema, ListResourceTemplatesRequestSchema, ListPromptsRequestSchema, GetPromptRequestSchema, } from '@modelcontextprotocol/sdk/types.js';
|
|
16
|
+
import { GITNEXUS_TOOLS } from './tools.js';
|
|
17
|
+
import { getResourceDefinitions, getResourceTemplates, readResource } from './resources.js';
|
|
18
|
+
/**
|
|
19
|
+
* Next-step hints appended to tool responses.
|
|
20
|
+
*
|
|
21
|
+
* Agents often stop after one tool call. These hints guide them to the
|
|
22
|
+
* logical next action, creating a self-guiding workflow without hooks.
|
|
23
|
+
*
|
|
24
|
+
* Design: Each hint is a short, actionable instruction (not a suggestion).
|
|
25
|
+
* The hint references the specific tool/resource to use next.
|
|
26
|
+
*/
|
|
27
|
+
function getNextStepHint(toolName, args) {
|
|
28
|
+
const repo = args?.repo;
|
|
29
|
+
const repoParam = repo ? `, repo: "${repo}"` : '';
|
|
30
|
+
const repoPath = repo || '{name}';
|
|
31
|
+
switch (toolName) {
|
|
32
|
+
case 'list_repos':
|
|
33
|
+
return `\n\n---\n**Next:** READ gitnexus://repo/{name}/context for any repo above to get its overview and check staleness.`;
|
|
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.`;
|
|
38
|
+
case 'impact':
|
|
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.`;
|
|
44
|
+
case 'cypher':
|
|
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.`;
|
|
53
|
+
default:
|
|
54
|
+
return '';
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Create a configured MCP Server with all handlers registered.
|
|
59
|
+
* Transport-agnostic — caller connects the desired transport.
|
|
60
|
+
*/
|
|
61
|
+
export function createMCPServer(backend) {
|
|
62
|
+
const server = new Server({
|
|
63
|
+
name: 'gitnexus',
|
|
64
|
+
version: '1.1.9',
|
|
65
|
+
}, {
|
|
66
|
+
capabilities: {
|
|
67
|
+
tools: {},
|
|
68
|
+
resources: {},
|
|
69
|
+
prompts: {},
|
|
70
|
+
},
|
|
71
|
+
});
|
|
72
|
+
// Handle list resources request
|
|
73
|
+
server.setRequestHandler(ListResourcesRequestSchema, async () => {
|
|
74
|
+
const resources = getResourceDefinitions();
|
|
75
|
+
return {
|
|
76
|
+
resources: resources.map(r => ({
|
|
77
|
+
uri: r.uri,
|
|
78
|
+
name: r.name,
|
|
79
|
+
description: r.description,
|
|
80
|
+
mimeType: r.mimeType,
|
|
81
|
+
})),
|
|
82
|
+
};
|
|
83
|
+
});
|
|
84
|
+
// Handle list resource templates request (for dynamic resources)
|
|
85
|
+
server.setRequestHandler(ListResourceTemplatesRequestSchema, async () => {
|
|
86
|
+
const templates = getResourceTemplates();
|
|
87
|
+
return {
|
|
88
|
+
resourceTemplates: templates.map(t => ({
|
|
89
|
+
uriTemplate: t.uriTemplate,
|
|
90
|
+
name: t.name,
|
|
91
|
+
description: t.description,
|
|
92
|
+
mimeType: t.mimeType,
|
|
93
|
+
})),
|
|
94
|
+
};
|
|
95
|
+
});
|
|
96
|
+
// Handle read resource request
|
|
97
|
+
server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
|
|
98
|
+
const { uri } = request.params;
|
|
99
|
+
try {
|
|
100
|
+
const content = await readResource(uri, backend);
|
|
101
|
+
return {
|
|
102
|
+
contents: [
|
|
103
|
+
{
|
|
104
|
+
uri,
|
|
105
|
+
mimeType: 'text/yaml',
|
|
106
|
+
text: content,
|
|
107
|
+
},
|
|
108
|
+
],
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
catch (err) {
|
|
112
|
+
return {
|
|
113
|
+
contents: [
|
|
114
|
+
{
|
|
115
|
+
uri,
|
|
116
|
+
mimeType: 'text/plain',
|
|
117
|
+
text: `Error: ${err.message}`,
|
|
118
|
+
},
|
|
119
|
+
],
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
// Handle list tools request
|
|
124
|
+
server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
125
|
+
tools: GITNEXUS_TOOLS.map((tool) => ({
|
|
126
|
+
name: tool.name,
|
|
127
|
+
description: tool.description,
|
|
128
|
+
inputSchema: tool.inputSchema,
|
|
129
|
+
})),
|
|
130
|
+
}));
|
|
131
|
+
// Handle tool calls — append next-step hints to guide agent workflow
|
|
132
|
+
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
133
|
+
const { name, arguments: args } = request.params;
|
|
134
|
+
try {
|
|
135
|
+
const result = await backend.callTool(name, args);
|
|
136
|
+
const resultText = typeof result === 'string' ? result : JSON.stringify(result, null, 2);
|
|
137
|
+
const hint = getNextStepHint(name, args);
|
|
138
|
+
return {
|
|
139
|
+
content: [
|
|
140
|
+
{
|
|
141
|
+
type: 'text',
|
|
142
|
+
text: resultText + hint,
|
|
143
|
+
},
|
|
144
|
+
],
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
catch (error) {
|
|
148
|
+
const message = error instanceof Error ? error.message : 'Unknown error';
|
|
149
|
+
return {
|
|
150
|
+
content: [
|
|
151
|
+
{
|
|
152
|
+
type: 'text',
|
|
153
|
+
text: `Error: ${message}`,
|
|
154
|
+
},
|
|
155
|
+
],
|
|
156
|
+
isError: true,
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
});
|
|
160
|
+
// Handle list prompts request
|
|
161
|
+
server.setRequestHandler(ListPromptsRequestSchema, async () => ({
|
|
162
|
+
prompts: [
|
|
163
|
+
{
|
|
164
|
+
name: 'detect_impact',
|
|
165
|
+
description: 'Analyze the impact of your current changes before committing. Guides through scope selection, change detection, process analysis, and risk assessment.',
|
|
166
|
+
arguments: [
|
|
167
|
+
{ name: 'scope', description: 'What to analyze: unstaged, staged, all, or compare', required: false },
|
|
168
|
+
{ name: 'base_ref', description: 'Branch/commit for compare scope', required: false },
|
|
169
|
+
],
|
|
170
|
+
},
|
|
171
|
+
{
|
|
172
|
+
name: 'generate_map',
|
|
173
|
+
description: 'Generate architecture documentation from the knowledge graph. Creates a codebase overview with execution flows and mermaid diagrams.',
|
|
174
|
+
arguments: [
|
|
175
|
+
{ name: 'repo', description: 'Repository name (omit if only one indexed)', required: false },
|
|
176
|
+
],
|
|
177
|
+
},
|
|
178
|
+
],
|
|
179
|
+
}));
|
|
180
|
+
// Handle get prompt request
|
|
181
|
+
server.setRequestHandler(GetPromptRequestSchema, async (request) => {
|
|
182
|
+
const { name, arguments: args } = request.params;
|
|
183
|
+
if (name === 'detect_impact') {
|
|
184
|
+
const scope = args?.scope || 'all';
|
|
185
|
+
const baseRef = args?.base_ref || '';
|
|
186
|
+
return {
|
|
187
|
+
messages: [
|
|
188
|
+
{
|
|
189
|
+
role: 'user',
|
|
190
|
+
content: {
|
|
191
|
+
type: 'text',
|
|
192
|
+
text: `Analyze the impact of my current code changes before committing.
|
|
193
|
+
|
|
194
|
+
Follow these steps:
|
|
195
|
+
1. Run \`detect_changes(${JSON.stringify({ scope, ...(baseRef ? { base_ref: baseRef } : {}) })})\` to find what changed and affected processes
|
|
196
|
+
2. For each changed symbol in critical processes, run \`context({name: "<symbol>"})\` to see its full reference graph
|
|
197
|
+
3. For any high-risk items (many callers or cross-process), run \`impact({target: "<symbol>", direction: "upstream"})\` for blast radius
|
|
198
|
+
4. Summarize: changes, affected processes, risk level, and recommended actions
|
|
199
|
+
|
|
200
|
+
Present the analysis as a clear risk report.`,
|
|
201
|
+
},
|
|
202
|
+
},
|
|
203
|
+
],
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
if (name === 'generate_map') {
|
|
207
|
+
const repo = args?.repo || '';
|
|
208
|
+
return {
|
|
209
|
+
messages: [
|
|
210
|
+
{
|
|
211
|
+
role: 'user',
|
|
212
|
+
content: {
|
|
213
|
+
type: 'text',
|
|
214
|
+
text: `Generate architecture documentation for this codebase using the knowledge graph.
|
|
215
|
+
|
|
216
|
+
Follow these steps:
|
|
217
|
+
1. READ \`gitnexus://repo/${repo || '{name}'}/context\` for codebase stats
|
|
218
|
+
2. READ \`gitnexus://repo/${repo || '{name}'}/clusters\` to see all functional areas
|
|
219
|
+
3. READ \`gitnexus://repo/${repo || '{name}'}/processes\` to see all execution flows
|
|
220
|
+
4. For the top 5 most important processes, READ \`gitnexus://repo/${repo || '{name}'}/process/{name}\` for step-by-step traces
|
|
221
|
+
5. Generate a mermaid architecture diagram showing the major areas and their connections
|
|
222
|
+
6. Write an ARCHITECTURE.md file with: overview, functional areas, key execution flows, and the mermaid diagram`,
|
|
223
|
+
},
|
|
224
|
+
},
|
|
225
|
+
],
|
|
226
|
+
};
|
|
227
|
+
}
|
|
228
|
+
throw new Error(`Unknown prompt: ${name}`);
|
|
229
|
+
});
|
|
230
|
+
return server;
|
|
231
|
+
}
|
|
232
|
+
/**
|
|
233
|
+
* Start the MCP server on stdio transport (for CLI use).
|
|
234
|
+
*/
|
|
235
|
+
export async function startMCPServer(backend) {
|
|
236
|
+
const server = createMCPServer(backend);
|
|
237
|
+
// Connect to stdio transport
|
|
238
|
+
const transport = new StdioServerTransport();
|
|
239
|
+
await server.connect(transport);
|
|
240
|
+
// Handle graceful shutdown
|
|
241
|
+
process.on('SIGINT', async () => {
|
|
242
|
+
await backend.disconnect();
|
|
243
|
+
await server.close();
|
|
244
|
+
process.exit(0);
|
|
245
|
+
});
|
|
246
|
+
process.on('SIGTERM', async () => {
|
|
247
|
+
await backend.disconnect();
|
|
248
|
+
await server.close();
|
|
249
|
+
process.exit(0);
|
|
250
|
+
});
|
|
251
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Staleness Check
|
|
3
|
+
*
|
|
4
|
+
* Checks if the GitNexus index is behind the current git HEAD.
|
|
5
|
+
* Returns a hint for the LLM to call analyze if stale.
|
|
6
|
+
*/
|
|
7
|
+
export interface StalenessInfo {
|
|
8
|
+
isStale: boolean;
|
|
9
|
+
commitsBehind: number;
|
|
10
|
+
hint?: string;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Check how many commits the index is behind HEAD
|
|
14
|
+
*/
|
|
15
|
+
export declare function checkStaleness(repoPath: string, lastCommit: string): StalenessInfo;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Staleness Check
|
|
3
|
+
*
|
|
4
|
+
* Checks if the GitNexus index is behind the current git HEAD.
|
|
5
|
+
* Returns a hint for the LLM to call analyze if stale.
|
|
6
|
+
*/
|
|
7
|
+
import { execSync } from 'child_process';
|
|
8
|
+
/**
|
|
9
|
+
* Check how many commits the index is behind HEAD
|
|
10
|
+
*/
|
|
11
|
+
export function checkStaleness(repoPath, lastCommit) {
|
|
12
|
+
try {
|
|
13
|
+
// Get count of commits between lastCommit and HEAD
|
|
14
|
+
const result = execSync(`git rev-list --count ${lastCommit}..HEAD`, { cwd: repoPath, encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'] }).trim();
|
|
15
|
+
const commitsBehind = parseInt(result, 10) || 0;
|
|
16
|
+
if (commitsBehind > 0) {
|
|
17
|
+
return {
|
|
18
|
+
isStale: true,
|
|
19
|
+
commitsBehind,
|
|
20
|
+
hint: `⚠️ Index is ${commitsBehind} commit${commitsBehind > 1 ? 's' : ''} behind HEAD. Run analyze tool to update.`,
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
return { isStale: false, commitsBehind: 0 };
|
|
24
|
+
}
|
|
25
|
+
catch {
|
|
26
|
+
// If git command fails, assume not stale (fail open)
|
|
27
|
+
return { isStale: false, commitsBehind: 0 };
|
|
28
|
+
}
|
|
29
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP Tool Definitions
|
|
3
|
+
*
|
|
4
|
+
* Defines the tools that GitNexus exposes to external AI agents.
|
|
5
|
+
* All tools support an optional `repo` parameter for multi-repo setups.
|
|
6
|
+
*/
|
|
7
|
+
export interface ToolDefinition {
|
|
8
|
+
name: string;
|
|
9
|
+
description: string;
|
|
10
|
+
inputSchema: {
|
|
11
|
+
type: 'object';
|
|
12
|
+
properties: Record<string, {
|
|
13
|
+
type: string;
|
|
14
|
+
description?: string;
|
|
15
|
+
default?: any;
|
|
16
|
+
items?: {
|
|
17
|
+
type: string;
|
|
18
|
+
};
|
|
19
|
+
enum?: string[];
|
|
20
|
+
}>;
|
|
21
|
+
required: string[];
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
export declare const GITNEXUS_TOOLS: ToolDefinition[];
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP Tool Definitions
|
|
3
|
+
*
|
|
4
|
+
* Defines the tools that GitNexus exposes to external AI agents.
|
|
5
|
+
* All tools support an optional `repo` parameter for multi-repo setups.
|
|
6
|
+
*/
|
|
7
|
+
export const GITNEXUS_TOOLS = [
|
|
8
|
+
{
|
|
9
|
+
name: 'list_repos',
|
|
10
|
+
description: `List all indexed repositories available to GitNexus.
|
|
11
|
+
|
|
12
|
+
Returns each repo's name, path, indexed date, last commit, and stats.
|
|
13
|
+
|
|
14
|
+
WHEN TO USE: First step when multiple repos are indexed, or to discover available repos.
|
|
15
|
+
AFTER THIS: READ gitnexus://repo/{name}/context for the repo you want to work with.
|
|
16
|
+
|
|
17
|
+
When multiple repos are indexed, you MUST specify the "repo" parameter
|
|
18
|
+
on other tools (query, context, impact, etc.) to target the correct one.`,
|
|
19
|
+
inputSchema: {
|
|
20
|
+
type: 'object',
|
|
21
|
+
properties: {},
|
|
22
|
+
required: [],
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
name: 'query',
|
|
27
|
+
description: `Query the code knowledge graph for execution flows related to a concept.
|
|
28
|
+
Returns processes (call chains) ranked by relevance, each with its symbols and file locations.
|
|
29
|
+
|
|
30
|
+
WHEN TO USE: Understanding how code works together. Use this when you need execution flows and relationships, not just file matches. Complements grep/IDE search.
|
|
31
|
+
AFTER THIS: Use context() on a specific symbol for 360-degree view (callers, callees, categorized refs).
|
|
32
|
+
|
|
33
|
+
Returns results grouped by process (execution flow):
|
|
34
|
+
- processes: ranked execution flows with relevance priority
|
|
35
|
+
- process_symbols: all symbols in those flows with file locations and module (functional area)
|
|
36
|
+
- definitions: standalone types/interfaces not in any process
|
|
37
|
+
|
|
38
|
+
Hybrid ranking: BM25 keyword + semantic vector search, ranked by Reciprocal Rank Fusion.`,
|
|
39
|
+
inputSchema: {
|
|
40
|
+
type: 'object',
|
|
41
|
+
properties: {
|
|
42
|
+
query: { type: 'string', description: 'Natural language or keyword search query' },
|
|
43
|
+
task_context: { type: 'string', description: 'What you are working on (e.g., "adding OAuth support"). Helps ranking.' },
|
|
44
|
+
goal: { type: 'string', description: 'What you want to find (e.g., "existing auth validation logic"). Helps ranking.' },
|
|
45
|
+
limit: { type: 'number', description: 'Max processes to return (default: 5)', default: 5 },
|
|
46
|
+
max_symbols: { type: 'number', description: 'Max symbols per process (default: 10)', default: 10 },
|
|
47
|
+
include_content: { type: 'boolean', description: 'Include full symbol source code (default: false)', default: false },
|
|
48
|
+
repo: { type: 'string', description: 'Repository name or path. Omit if only one repo is indexed.' },
|
|
49
|
+
},
|
|
50
|
+
required: ['query'],
|
|
51
|
+
},
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
name: 'cypher',
|
|
55
|
+
description: `Execute Cypher query against the code knowledge graph.
|
|
56
|
+
|
|
57
|
+
WHEN TO USE: Complex structural queries that search/explore can't answer. READ gitnexus://repo/{name}/schema first for the full schema.
|
|
58
|
+
AFTER THIS: Use context() on result symbols for deeper context.
|
|
59
|
+
|
|
60
|
+
SCHEMA:
|
|
61
|
+
- Nodes: File, Folder, Function, Class, Interface, Method, CodeElement, Community, Process
|
|
62
|
+
- Multi-language nodes (use backticks): \`Struct\`, \`Enum\`, \`Trait\`, \`Impl\`, etc.
|
|
63
|
+
- All edges via single CodeRelation table with 'type' property
|
|
64
|
+
- Edge types: CONTAINS, DEFINES, CALLS, IMPORTS, EXTENDS, IMPLEMENTS, MEMBER_OF, STEP_IN_PROCESS
|
|
65
|
+
- Edge properties: type (STRING), confidence (DOUBLE), reason (STRING), step (INT32)
|
|
66
|
+
|
|
67
|
+
EXAMPLES:
|
|
68
|
+
• Find callers of a function:
|
|
69
|
+
MATCH (a)-[:CodeRelation {type: 'CALLS'}]->(b:Function {name: "validateUser"}) RETURN a.name, a.filePath
|
|
70
|
+
|
|
71
|
+
• Find community members:
|
|
72
|
+
MATCH (f)-[:CodeRelation {type: 'MEMBER_OF'}]->(c:Community) WHERE c.heuristicLabel = "Auth" RETURN f.name
|
|
73
|
+
|
|
74
|
+
• Trace a process:
|
|
75
|
+
MATCH (s)-[r:CodeRelation {type: 'STEP_IN_PROCESS'}]->(p:Process) WHERE p.heuristicLabel = "UserLogin" RETURN s.name, r.step ORDER BY r.step
|
|
76
|
+
|
|
77
|
+
OUTPUT: Returns { markdown, row_count } — results formatted as a Markdown table for easy reading.
|
|
78
|
+
|
|
79
|
+
TIPS:
|
|
80
|
+
- All relationships use single CodeRelation table — filter with {type: 'CALLS'} etc.
|
|
81
|
+
- Community = auto-detected functional area (Leiden algorithm)
|
|
82
|
+
- Process = execution flow trace from entry point to terminal
|
|
83
|
+
- Use heuristicLabel (not label) for human-readable community/process names`,
|
|
84
|
+
inputSchema: {
|
|
85
|
+
type: 'object',
|
|
86
|
+
properties: {
|
|
87
|
+
query: { type: 'string', description: 'Cypher query to execute' },
|
|
88
|
+
repo: { type: 'string', description: 'Repository name or path. Omit if only one repo is indexed.' },
|
|
89
|
+
},
|
|
90
|
+
required: ['query'],
|
|
91
|
+
},
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
name: 'context',
|
|
95
|
+
description: `360-degree view of a single code symbol.
|
|
96
|
+
Shows categorized incoming/outgoing references (calls, imports, extends, implements), process participation, and file location.
|
|
97
|
+
|
|
98
|
+
WHEN TO USE: After query() to understand a specific symbol in depth. When you need to know all callers, callees, and what execution flows a symbol participates in.
|
|
99
|
+
AFTER THIS: Use impact() if planning changes, or READ gitnexus://repo/{name}/process/{processName} for full execution trace.
|
|
100
|
+
|
|
101
|
+
Handles disambiguation: if multiple symbols share the same name, returns candidates for you to pick from. Use uid param for zero-ambiguity lookup from prior results.`,
|
|
102
|
+
inputSchema: {
|
|
103
|
+
type: 'object',
|
|
104
|
+
properties: {
|
|
105
|
+
name: { type: 'string', description: 'Symbol name (e.g., "validateUser", "AuthService")' },
|
|
106
|
+
uid: { type: 'string', description: 'Direct symbol UID from prior tool results (zero-ambiguity lookup)' },
|
|
107
|
+
file_path: { type: 'string', description: 'File path to disambiguate common names' },
|
|
108
|
+
include_content: { type: 'boolean', description: 'Include full symbol source code (default: false)', default: false },
|
|
109
|
+
repo: { type: 'string', description: 'Repository name or path. Omit if only one repo is indexed.' },
|
|
110
|
+
},
|
|
111
|
+
required: [],
|
|
112
|
+
},
|
|
113
|
+
},
|
|
114
|
+
{
|
|
115
|
+
name: 'detect_changes',
|
|
116
|
+
description: `Analyze uncommitted git changes and find affected execution flows.
|
|
117
|
+
Maps git diff hunks to indexed symbols, then traces which processes are impacted.
|
|
118
|
+
|
|
119
|
+
WHEN TO USE: Before committing — to understand what your changes affect. Pre-commit review, PR preparation.
|
|
120
|
+
AFTER THIS: Review affected processes. Use context() on high-risk symbols. READ gitnexus://repo/{name}/process/{name} for full traces.
|
|
121
|
+
|
|
122
|
+
Returns: changed symbols, affected processes, and a risk summary.`,
|
|
123
|
+
inputSchema: {
|
|
124
|
+
type: 'object',
|
|
125
|
+
properties: {
|
|
126
|
+
scope: { type: 'string', description: 'What to analyze: "unstaged" (default), "staged", "all", or "compare"', enum: ['unstaged', 'staged', 'all', 'compare'], default: 'unstaged' },
|
|
127
|
+
base_ref: { type: 'string', description: 'Branch/commit for "compare" scope (e.g., "main")' },
|
|
128
|
+
repo: { type: 'string', description: 'Repository name or path. Omit if only one repo is indexed.' },
|
|
129
|
+
},
|
|
130
|
+
required: [],
|
|
131
|
+
},
|
|
132
|
+
},
|
|
133
|
+
{
|
|
134
|
+
name: 'rename',
|
|
135
|
+
description: `Multi-file coordinated rename using the knowledge graph + text search.
|
|
136
|
+
Finds all references via graph (high confidence) and regex text search (lower confidence). Preview by default.
|
|
137
|
+
|
|
138
|
+
WHEN TO USE: Renaming a function, class, method, or variable across the codebase. Safer than find-and-replace.
|
|
139
|
+
AFTER THIS: Run detect_changes() to verify no unexpected side effects.
|
|
140
|
+
|
|
141
|
+
Each edit is tagged with confidence:
|
|
142
|
+
- "graph": found via knowledge graph relationships (high confidence, safe to accept)
|
|
143
|
+
- "text_search": found via regex text search (lower confidence, review carefully)`,
|
|
144
|
+
inputSchema: {
|
|
145
|
+
type: 'object',
|
|
146
|
+
properties: {
|
|
147
|
+
symbol_name: { type: 'string', description: 'Current symbol name to rename' },
|
|
148
|
+
symbol_uid: { type: 'string', description: 'Direct symbol UID from prior tool results (zero-ambiguity)' },
|
|
149
|
+
new_name: { type: 'string', description: 'The new name for the symbol' },
|
|
150
|
+
file_path: { type: 'string', description: 'File path to disambiguate common names' },
|
|
151
|
+
dry_run: { type: 'boolean', description: 'Preview edits without modifying files (default: true)', default: true },
|
|
152
|
+
repo: { type: 'string', description: 'Repository name or path. Omit if only one repo is indexed.' },
|
|
153
|
+
},
|
|
154
|
+
required: ['new_name'],
|
|
155
|
+
},
|
|
156
|
+
},
|
|
157
|
+
{
|
|
158
|
+
name: 'impact',
|
|
159
|
+
description: `Analyze the blast radius of changing a code symbol.
|
|
160
|
+
Returns affected symbols grouped by depth, plus risk assessment, affected execution flows, and affected modules.
|
|
161
|
+
|
|
162
|
+
WHEN TO USE: Before making code changes — especially refactoring, renaming, or modifying shared code. Shows what would break.
|
|
163
|
+
AFTER THIS: Review d=1 items (WILL BREAK). Use context() on high-risk symbols.
|
|
164
|
+
|
|
165
|
+
Output includes:
|
|
166
|
+
- risk: LOW / MEDIUM / HIGH / CRITICAL
|
|
167
|
+
- summary: direct callers, processes affected, modules affected
|
|
168
|
+
- affected_processes: which execution flows break and at which step
|
|
169
|
+
- affected_modules: which functional areas are hit (direct vs indirect)
|
|
170
|
+
- byDepth: all affected symbols grouped by traversal depth
|
|
171
|
+
|
|
172
|
+
Depth groups:
|
|
173
|
+
- d=1: WILL BREAK (direct callers/importers)
|
|
174
|
+
- d=2: LIKELY AFFECTED (indirect)
|
|
175
|
+
- d=3: MAY NEED TESTING (transitive)
|
|
176
|
+
|
|
177
|
+
EdgeType: CALLS, IMPORTS, EXTENDS, IMPLEMENTS
|
|
178
|
+
Confidence: 1.0 = certain, <0.8 = fuzzy match`,
|
|
179
|
+
inputSchema: {
|
|
180
|
+
type: 'object',
|
|
181
|
+
properties: {
|
|
182
|
+
target: { type: 'string', description: 'Name of function, class, or file to analyze' },
|
|
183
|
+
target_uid: { type: 'string', description: 'Optional exact symbol UID (preferred when target name is ambiguous)' },
|
|
184
|
+
file_path: { type: 'string', description: 'Optional file path filter to disambiguate target name' },
|
|
185
|
+
direction: { type: 'string', description: 'upstream (what depends on this) or downstream (what this depends on)' },
|
|
186
|
+
maxDepth: { type: 'number', description: 'Max relationship depth (default: 3)', default: 3 },
|
|
187
|
+
relationTypes: { type: 'array', items: { type: 'string' }, description: 'Filter: CALLS, IMPORTS, EXTENDS, IMPLEMENTS (default: usage-based)' },
|
|
188
|
+
includeTests: { type: 'boolean', description: 'Include test files (default: false)' },
|
|
189
|
+
minConfidence: { type: 'number', description: 'Minimum confidence 0-1 (default: 0.3)' },
|
|
190
|
+
repo: { type: 'string', description: 'Repository name or path. Omit if only one repo is indexed.' },
|
|
191
|
+
},
|
|
192
|
+
required: ['target', 'direction'],
|
|
193
|
+
},
|
|
194
|
+
},
|
|
195
|
+
];
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HTTP API Server
|
|
3
|
+
*
|
|
4
|
+
* REST API for browser-based clients to query the local .gitnexus/ index.
|
|
5
|
+
* Also hosts the MCP server over StreamableHTTP for remote AI tool access.
|
|
6
|
+
*
|
|
7
|
+
* Security: binds to 127.0.0.1 by default (use --host to override).
|
|
8
|
+
* CORS is restricted to localhost and the deployed site.
|
|
9
|
+
*/
|
|
10
|
+
export declare const createServer: (port: number, host?: string) => Promise<void>;
|