@duytransipher/gitnexus 1.4.6-sipher.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.
Files changed (224) hide show
  1. package/LICENSE +73 -0
  2. package/README.md +261 -0
  3. package/dist/cli/ai-context.d.ts +23 -0
  4. package/dist/cli/ai-context.js +265 -0
  5. package/dist/cli/analyze.d.ts +12 -0
  6. package/dist/cli/analyze.js +345 -0
  7. package/dist/cli/augment.d.ts +13 -0
  8. package/dist/cli/augment.js +33 -0
  9. package/dist/cli/clean.d.ts +10 -0
  10. package/dist/cli/clean.js +60 -0
  11. package/dist/cli/eval-server.d.ts +37 -0
  12. package/dist/cli/eval-server.js +389 -0
  13. package/dist/cli/index.d.ts +2 -0
  14. package/dist/cli/index.js +137 -0
  15. package/dist/cli/lazy-action.d.ts +6 -0
  16. package/dist/cli/lazy-action.js +18 -0
  17. package/dist/cli/list.d.ts +6 -0
  18. package/dist/cli/list.js +30 -0
  19. package/dist/cli/mcp.d.ts +8 -0
  20. package/dist/cli/mcp.js +36 -0
  21. package/dist/cli/serve.d.ts +4 -0
  22. package/dist/cli/serve.js +6 -0
  23. package/dist/cli/setup.d.ts +8 -0
  24. package/dist/cli/setup.js +367 -0
  25. package/dist/cli/sipher-patched.d.ts +2 -0
  26. package/dist/cli/sipher-patched.js +77 -0
  27. package/dist/cli/skill-gen.d.ts +26 -0
  28. package/dist/cli/skill-gen.js +549 -0
  29. package/dist/cli/status.d.ts +6 -0
  30. package/dist/cli/status.js +36 -0
  31. package/dist/cli/tool.d.ts +60 -0
  32. package/dist/cli/tool.js +180 -0
  33. package/dist/cli/wiki.d.ts +15 -0
  34. package/dist/cli/wiki.js +365 -0
  35. package/dist/config/ignore-service.d.ts +26 -0
  36. package/dist/config/ignore-service.js +284 -0
  37. package/dist/config/supported-languages.d.ts +15 -0
  38. package/dist/config/supported-languages.js +16 -0
  39. package/dist/core/augmentation/engine.d.ts +26 -0
  40. package/dist/core/augmentation/engine.js +240 -0
  41. package/dist/core/embeddings/embedder.d.ts +60 -0
  42. package/dist/core/embeddings/embedder.js +251 -0
  43. package/dist/core/embeddings/embedding-pipeline.d.ts +51 -0
  44. package/dist/core/embeddings/embedding-pipeline.js +356 -0
  45. package/dist/core/embeddings/index.d.ts +9 -0
  46. package/dist/core/embeddings/index.js +9 -0
  47. package/dist/core/embeddings/text-generator.d.ts +24 -0
  48. package/dist/core/embeddings/text-generator.js +182 -0
  49. package/dist/core/embeddings/types.d.ts +87 -0
  50. package/dist/core/embeddings/types.js +32 -0
  51. package/dist/core/graph/graph.d.ts +2 -0
  52. package/dist/core/graph/graph.js +66 -0
  53. package/dist/core/graph/types.d.ts +66 -0
  54. package/dist/core/graph/types.js +1 -0
  55. package/dist/core/ingestion/ast-cache.d.ts +11 -0
  56. package/dist/core/ingestion/ast-cache.js +35 -0
  57. package/dist/core/ingestion/call-processor.d.ts +23 -0
  58. package/dist/core/ingestion/call-processor.js +793 -0
  59. package/dist/core/ingestion/call-routing.d.ts +68 -0
  60. package/dist/core/ingestion/call-routing.js +129 -0
  61. package/dist/core/ingestion/cluster-enricher.d.ts +38 -0
  62. package/dist/core/ingestion/cluster-enricher.js +170 -0
  63. package/dist/core/ingestion/community-processor.d.ts +39 -0
  64. package/dist/core/ingestion/community-processor.js +312 -0
  65. package/dist/core/ingestion/constants.d.ts +16 -0
  66. package/dist/core/ingestion/constants.js +16 -0
  67. package/dist/core/ingestion/entry-point-scoring.d.ts +40 -0
  68. package/dist/core/ingestion/entry-point-scoring.js +353 -0
  69. package/dist/core/ingestion/export-detection.d.ts +18 -0
  70. package/dist/core/ingestion/export-detection.js +231 -0
  71. package/dist/core/ingestion/filesystem-walker.d.ts +28 -0
  72. package/dist/core/ingestion/filesystem-walker.js +81 -0
  73. package/dist/core/ingestion/framework-detection.d.ts +54 -0
  74. package/dist/core/ingestion/framework-detection.js +411 -0
  75. package/dist/core/ingestion/heritage-processor.d.ts +28 -0
  76. package/dist/core/ingestion/heritage-processor.js +251 -0
  77. package/dist/core/ingestion/import-processor.d.ts +34 -0
  78. package/dist/core/ingestion/import-processor.js +398 -0
  79. package/dist/core/ingestion/language-config.d.ts +46 -0
  80. package/dist/core/ingestion/language-config.js +167 -0
  81. package/dist/core/ingestion/mro-processor.d.ts +45 -0
  82. package/dist/core/ingestion/mro-processor.js +369 -0
  83. package/dist/core/ingestion/named-binding-extraction.d.ts +61 -0
  84. package/dist/core/ingestion/named-binding-extraction.js +363 -0
  85. package/dist/core/ingestion/parsing-processor.d.ts +19 -0
  86. package/dist/core/ingestion/parsing-processor.js +315 -0
  87. package/dist/core/ingestion/pipeline.d.ts +6 -0
  88. package/dist/core/ingestion/pipeline.js +401 -0
  89. package/dist/core/ingestion/process-processor.d.ts +51 -0
  90. package/dist/core/ingestion/process-processor.js +315 -0
  91. package/dist/core/ingestion/resolution-context.d.ts +53 -0
  92. package/dist/core/ingestion/resolution-context.js +132 -0
  93. package/dist/core/ingestion/resolvers/csharp.d.ts +22 -0
  94. package/dist/core/ingestion/resolvers/csharp.js +109 -0
  95. package/dist/core/ingestion/resolvers/go.d.ts +19 -0
  96. package/dist/core/ingestion/resolvers/go.js +42 -0
  97. package/dist/core/ingestion/resolvers/index.d.ts +18 -0
  98. package/dist/core/ingestion/resolvers/index.js +13 -0
  99. package/dist/core/ingestion/resolvers/jvm.d.ts +23 -0
  100. package/dist/core/ingestion/resolvers/jvm.js +87 -0
  101. package/dist/core/ingestion/resolvers/php.d.ts +15 -0
  102. package/dist/core/ingestion/resolvers/php.js +35 -0
  103. package/dist/core/ingestion/resolvers/python.d.ts +19 -0
  104. package/dist/core/ingestion/resolvers/python.js +52 -0
  105. package/dist/core/ingestion/resolvers/ruby.d.ts +12 -0
  106. package/dist/core/ingestion/resolvers/ruby.js +15 -0
  107. package/dist/core/ingestion/resolvers/rust.d.ts +15 -0
  108. package/dist/core/ingestion/resolvers/rust.js +73 -0
  109. package/dist/core/ingestion/resolvers/standard.d.ts +28 -0
  110. package/dist/core/ingestion/resolvers/standard.js +123 -0
  111. package/dist/core/ingestion/resolvers/utils.d.ts +33 -0
  112. package/dist/core/ingestion/resolvers/utils.js +122 -0
  113. package/dist/core/ingestion/structure-processor.d.ts +2 -0
  114. package/dist/core/ingestion/structure-processor.js +36 -0
  115. package/dist/core/ingestion/symbol-table.d.ts +63 -0
  116. package/dist/core/ingestion/symbol-table.js +85 -0
  117. package/dist/core/ingestion/tree-sitter-queries.d.ts +15 -0
  118. package/dist/core/ingestion/tree-sitter-queries.js +888 -0
  119. package/dist/core/ingestion/type-env.d.ts +49 -0
  120. package/dist/core/ingestion/type-env.js +613 -0
  121. package/dist/core/ingestion/type-extractors/c-cpp.d.ts +2 -0
  122. package/dist/core/ingestion/type-extractors/c-cpp.js +385 -0
  123. package/dist/core/ingestion/type-extractors/csharp.d.ts +2 -0
  124. package/dist/core/ingestion/type-extractors/csharp.js +383 -0
  125. package/dist/core/ingestion/type-extractors/go.d.ts +2 -0
  126. package/dist/core/ingestion/type-extractors/go.js +467 -0
  127. package/dist/core/ingestion/type-extractors/index.d.ts +22 -0
  128. package/dist/core/ingestion/type-extractors/index.js +31 -0
  129. package/dist/core/ingestion/type-extractors/jvm.d.ts +3 -0
  130. package/dist/core/ingestion/type-extractors/jvm.js +681 -0
  131. package/dist/core/ingestion/type-extractors/php.d.ts +2 -0
  132. package/dist/core/ingestion/type-extractors/php.js +549 -0
  133. package/dist/core/ingestion/type-extractors/python.d.ts +2 -0
  134. package/dist/core/ingestion/type-extractors/python.js +455 -0
  135. package/dist/core/ingestion/type-extractors/ruby.d.ts +2 -0
  136. package/dist/core/ingestion/type-extractors/ruby.js +389 -0
  137. package/dist/core/ingestion/type-extractors/rust.d.ts +2 -0
  138. package/dist/core/ingestion/type-extractors/rust.js +456 -0
  139. package/dist/core/ingestion/type-extractors/shared.d.ts +145 -0
  140. package/dist/core/ingestion/type-extractors/shared.js +810 -0
  141. package/dist/core/ingestion/type-extractors/swift.d.ts +2 -0
  142. package/dist/core/ingestion/type-extractors/swift.js +137 -0
  143. package/dist/core/ingestion/type-extractors/types.d.ts +127 -0
  144. package/dist/core/ingestion/type-extractors/types.js +1 -0
  145. package/dist/core/ingestion/type-extractors/typescript.d.ts +2 -0
  146. package/dist/core/ingestion/type-extractors/typescript.js +494 -0
  147. package/dist/core/ingestion/utils.d.ts +138 -0
  148. package/dist/core/ingestion/utils.js +1290 -0
  149. package/dist/core/ingestion/workers/parse-worker.d.ts +122 -0
  150. package/dist/core/ingestion/workers/parse-worker.js +1126 -0
  151. package/dist/core/ingestion/workers/worker-pool.d.ts +16 -0
  152. package/dist/core/ingestion/workers/worker-pool.js +128 -0
  153. package/dist/core/lbug/csv-generator.d.ts +33 -0
  154. package/dist/core/lbug/csv-generator.js +366 -0
  155. package/dist/core/lbug/lbug-adapter.d.ts +103 -0
  156. package/dist/core/lbug/lbug-adapter.js +769 -0
  157. package/dist/core/lbug/schema.d.ts +53 -0
  158. package/dist/core/lbug/schema.js +430 -0
  159. package/dist/core/search/bm25-index.d.ts +23 -0
  160. package/dist/core/search/bm25-index.js +96 -0
  161. package/dist/core/search/hybrid-search.d.ts +49 -0
  162. package/dist/core/search/hybrid-search.js +118 -0
  163. package/dist/core/tree-sitter/parser-loader.d.ts +5 -0
  164. package/dist/core/tree-sitter/parser-loader.js +63 -0
  165. package/dist/core/wiki/generator.d.ts +120 -0
  166. package/dist/core/wiki/generator.js +939 -0
  167. package/dist/core/wiki/graph-queries.d.ts +80 -0
  168. package/dist/core/wiki/graph-queries.js +238 -0
  169. package/dist/core/wiki/html-viewer.d.ts +10 -0
  170. package/dist/core/wiki/html-viewer.js +297 -0
  171. package/dist/core/wiki/llm-client.d.ts +43 -0
  172. package/dist/core/wiki/llm-client.js +186 -0
  173. package/dist/core/wiki/prompts.d.ts +53 -0
  174. package/dist/core/wiki/prompts.js +174 -0
  175. package/dist/lib/utils.d.ts +1 -0
  176. package/dist/lib/utils.js +3 -0
  177. package/dist/mcp/compatible-stdio-transport.d.ts +25 -0
  178. package/dist/mcp/compatible-stdio-transport.js +200 -0
  179. package/dist/mcp/core/embedder.d.ts +27 -0
  180. package/dist/mcp/core/embedder.js +108 -0
  181. package/dist/mcp/core/lbug-adapter.d.ts +57 -0
  182. package/dist/mcp/core/lbug-adapter.js +455 -0
  183. package/dist/mcp/local/local-backend.d.ts +181 -0
  184. package/dist/mcp/local/local-backend.js +1722 -0
  185. package/dist/mcp/resources.d.ts +31 -0
  186. package/dist/mcp/resources.js +411 -0
  187. package/dist/mcp/server.d.ts +23 -0
  188. package/dist/mcp/server.js +296 -0
  189. package/dist/mcp/staleness.d.ts +15 -0
  190. package/dist/mcp/staleness.js +29 -0
  191. package/dist/mcp/tools.d.ts +24 -0
  192. package/dist/mcp/tools.js +292 -0
  193. package/dist/server/api.d.ts +10 -0
  194. package/dist/server/api.js +344 -0
  195. package/dist/server/mcp-http.d.ts +13 -0
  196. package/dist/server/mcp-http.js +100 -0
  197. package/dist/storage/git.d.ts +6 -0
  198. package/dist/storage/git.js +35 -0
  199. package/dist/storage/repo-manager.d.ts +138 -0
  200. package/dist/storage/repo-manager.js +299 -0
  201. package/dist/types/pipeline.d.ts +32 -0
  202. package/dist/types/pipeline.js +18 -0
  203. package/dist/unreal/bridge.d.ts +4 -0
  204. package/dist/unreal/bridge.js +113 -0
  205. package/dist/unreal/config.d.ts +6 -0
  206. package/dist/unreal/config.js +55 -0
  207. package/dist/unreal/types.d.ts +105 -0
  208. package/dist/unreal/types.js +1 -0
  209. package/hooks/claude/gitnexus-hook.cjs +238 -0
  210. package/hooks/claude/pre-tool-use.sh +79 -0
  211. package/hooks/claude/session-start.sh +42 -0
  212. package/package.json +100 -0
  213. package/scripts/ensure-cli-executable.cjs +21 -0
  214. package/scripts/patch-tree-sitter-swift.cjs +74 -0
  215. package/scripts/setup-unreal-gitnexus.ps1 +191 -0
  216. package/skills/gitnexus-cli.md +82 -0
  217. package/skills/gitnexus-debugging.md +89 -0
  218. package/skills/gitnexus-exploring.md +78 -0
  219. package/skills/gitnexus-guide.md +64 -0
  220. package/skills/gitnexus-impact-analysis.md +97 -0
  221. package/skills/gitnexus-pr-review.md +163 -0
  222. package/skills/gitnexus-refactoring.md +121 -0
  223. package/vendor/leiden/index.cjs +355 -0
  224. package/vendor/leiden/utils.cjs +392 -0
@@ -0,0 +1,31 @@
1
+ /**
2
+ * MCP Resources (Multi-Repo)
3
+ *
4
+ * Provides structured on-demand data to AI agents.
5
+ * All resources use repo-scoped URIs: gitnexus://repo/{name}/context
6
+ */
7
+ import type { LocalBackend } from './local/local-backend.js';
8
+ export interface ResourceDefinition {
9
+ uri: string;
10
+ name: string;
11
+ description: string;
12
+ mimeType: string;
13
+ }
14
+ export interface ResourceTemplate {
15
+ uriTemplate: string;
16
+ name: string;
17
+ description: string;
18
+ mimeType: string;
19
+ }
20
+ /**
21
+ * Static resources — includes per-repo resources and the global repos list
22
+ */
23
+ export declare function getResourceDefinitions(): ResourceDefinition[];
24
+ /**
25
+ * Dynamic resource templates
26
+ */
27
+ export declare function getResourceTemplates(): ResourceTemplate[];
28
+ /**
29
+ * Read a resource and return its content
30
+ */
31
+ export declare function readResource(uri: string, backend: LocalBackend): Promise<string>;
@@ -0,0 +1,411 @@
1
+ /**
2
+ * MCP Resources (Multi-Repo)
3
+ *
4
+ * Provides structured on-demand data to AI agents.
5
+ * All resources use repo-scoped URIs: gitnexus://repo/{name}/context
6
+ */
7
+ import { checkStaleness } from './staleness.js';
8
+ /**
9
+ * Static resources — includes per-repo resources and the global repos list
10
+ */
11
+ export function getResourceDefinitions() {
12
+ return [
13
+ {
14
+ uri: 'gitnexus://repos',
15
+ name: 'All Indexed Repositories',
16
+ description: 'List of all indexed repos with stats. Read this first to discover available repos.',
17
+ mimeType: 'text/yaml',
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
+ },
25
+ ];
26
+ }
27
+ /**
28
+ * Dynamic resource templates
29
+ */
30
+ export function getResourceTemplates() {
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
+ },
56
+ {
57
+ uriTemplate: 'gitnexus://repo/{name}/cluster/{clusterName}',
58
+ name: 'Module Detail',
59
+ description: 'Deep dive into a specific functional area',
60
+ mimeType: 'text/yaml',
61
+ },
62
+ {
63
+ uriTemplate: 'gitnexus://repo/{name}/process/{processName}',
64
+ name: 'Process Trace',
65
+ description: 'Step-by-step execution trace',
66
+ mimeType: 'text/yaml',
67
+ },
68
+ ];
69
+ }
70
+ /**
71
+ * Parse a resource URI to extract the repo name and resource type.
72
+ */
73
+ function parseUri(uri) {
74
+ if (uri === 'gitnexus://repos')
75
+ return { resourceType: 'repos' };
76
+ if (uri === 'gitnexus://setup')
77
+ return { resourceType: 'setup' };
78
+ // Repo-scoped: gitnexus://repo/{name}/context
79
+ const repoMatch = uri.match(/^gitnexus:\/\/repo\/([^/]+)\/(.+)$/);
80
+ if (repoMatch) {
81
+ const repoName = decodeURIComponent(repoMatch[1]);
82
+ const rest = repoMatch[2];
83
+ if (rest.startsWith('cluster/')) {
84
+ return { repoName, resourceType: 'cluster', param: decodeURIComponent(rest.replace('cluster/', '')) };
85
+ }
86
+ if (rest.startsWith('process/')) {
87
+ return { repoName, resourceType: 'process', param: decodeURIComponent(rest.replace('process/', '')) };
88
+ }
89
+ return { repoName, resourceType: rest };
90
+ }
91
+ throw new Error(`Unknown resource URI: ${uri}`);
92
+ }
93
+ /**
94
+ * Read a resource and return its content
95
+ */
96
+ export async function readResource(uri, backend) {
97
+ const parsed = parseUri(uri);
98
+ // Global repos list — no repo context needed
99
+ if (parsed.resourceType === 'repos') {
100
+ return getReposResource(backend);
101
+ }
102
+ // Setup resource — returns AGENTS.md content for all repos
103
+ if (parsed.resourceType === 'setup') {
104
+ return getSetupResource(backend);
105
+ }
106
+ const repoName = parsed.repoName;
107
+ switch (parsed.resourceType) {
108
+ case 'context':
109
+ return getContextResource(backend, repoName);
110
+ case 'clusters':
111
+ return getClustersResource(backend, repoName);
112
+ case 'processes':
113
+ return getProcessesResource(backend, repoName);
114
+ case 'schema':
115
+ return getSchemaResource();
116
+ case 'cluster':
117
+ return getClusterDetailResource(parsed.param, backend, repoName);
118
+ case 'process':
119
+ return getProcessDetailResource(parsed.param, backend, repoName);
120
+ default:
121
+ throw new Error(`Unknown resource: ${uri}`);
122
+ }
123
+ }
124
+ // ─── Resource Implementations ─────────────────────────────────────────
125
+ /**
126
+ * Repos resource — list all indexed repositories
127
+ */
128
+ async function getReposResource(backend) {
129
+ const repos = await backend.listRepos();
130
+ if (repos.length === 0) {
131
+ return 'repos: []\n# No repositories indexed. Run: gitnexus analyze';
132
+ }
133
+ const lines = ['repos:'];
134
+ for (const repo of repos) {
135
+ lines.push(` - name: "${repo.name}"`);
136
+ lines.push(` path: "${repo.path}"`);
137
+ lines.push(` indexed: "${repo.indexedAt}"`);
138
+ lines.push(` commit: "${repo.lastCommit?.slice(0, 7) || 'unknown'}"`);
139
+ if (repo.stats) {
140
+ lines.push(` files: ${repo.stats.files || 0}`);
141
+ lines.push(` symbols: ${repo.stats.nodes || 0}`);
142
+ lines.push(` processes: ${repo.stats.processes || 0}`);
143
+ }
144
+ }
145
+ if (repos.length > 1) {
146
+ lines.push('');
147
+ lines.push('# Multiple repos indexed. Use repo parameter in tool calls:');
148
+ lines.push(`# gitnexus_search({query: "auth", repo: "${repos[0].name}"})`);
149
+ }
150
+ return lines.join('\n');
151
+ }
152
+ /**
153
+ * Context resource — codebase overview for a specific repo
154
+ */
155
+ async function getContextResource(backend, repoName) {
156
+ // Resolve repo
157
+ const repo = await backend.resolveRepo(repoName);
158
+ const repoId = repo.name.toLowerCase();
159
+ const context = backend.getContext(repoId) || backend.getContext();
160
+ if (!context) {
161
+ return 'error: No codebase loaded. Run: gitnexus analyze';
162
+ }
163
+ // Check staleness
164
+ const repoPath = repo.repoPath;
165
+ const lastCommit = repo.lastCommit || 'HEAD';
166
+ const staleness = repoPath ? checkStaleness(repoPath, lastCommit) : { isStale: false, commitsBehind: 0 };
167
+ const lines = [
168
+ `project: ${context.projectName}`,
169
+ ];
170
+ if (staleness.isStale && staleness.hint) {
171
+ lines.push('');
172
+ lines.push(`staleness: "${staleness.hint}"`);
173
+ }
174
+ lines.push('');
175
+ lines.push('stats:');
176
+ lines.push(` files: ${context.stats.fileCount}`);
177
+ lines.push(` symbols: ${context.stats.functionCount}`);
178
+ lines.push(` processes: ${context.stats.processCount}`);
179
+ lines.push('');
180
+ lines.push('tools_available:');
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');
186
+ lines.push(' - cypher: Raw graph queries');
187
+ lines.push(' - list_repos: Discover all indexed repositories');
188
+ lines.push('');
189
+ lines.push('re_index: Run `npx gitnexus analyze` in terminal if data is stale');
190
+ lines.push('');
191
+ lines.push('resources_available:');
192
+ lines.push(' - gitnexus://repos: All indexed repositories');
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`);
196
+ lines.push(` - gitnexus://repo/${context.projectName}/process/{name}: Process trace`);
197
+ return lines.join('\n');
198
+ }
199
+ /**
200
+ * Clusters resource — queries graph directly via backend.queryClusters()
201
+ */
202
+ async function getClustersResource(backend, repoName) {
203
+ try {
204
+ const result = await backend.queryClusters(repoName, 100);
205
+ if (!result.clusters || result.clusters.length === 0) {
206
+ return 'modules: []\n# No functional areas detected. Run: gitnexus analyze';
207
+ }
208
+ const displayLimit = 20;
209
+ const lines = ['modules:'];
210
+ const toShow = result.clusters.slice(0, displayLimit);
211
+ for (const cluster of toShow) {
212
+ const label = cluster.heuristicLabel || cluster.label || cluster.id;
213
+ lines.push(` - name: "${label}"`);
214
+ lines.push(` symbols: ${cluster.symbolCount || 0}`);
215
+ if (cluster.cohesion) {
216
+ lines.push(` cohesion: ${(cluster.cohesion * 100).toFixed(0)}%`);
217
+ }
218
+ }
219
+ if (result.clusters.length > displayLimit) {
220
+ lines.push(`\n# Showing top ${displayLimit} of ${result.clusters.length} modules. Use gitnexus_query for deeper search.`);
221
+ }
222
+ return lines.join('\n');
223
+ }
224
+ catch (err) {
225
+ return `error: ${err.message}`;
226
+ }
227
+ }
228
+ /**
229
+ * Processes resource — queries graph directly via backend.queryProcesses()
230
+ */
231
+ async function getProcessesResource(backend, repoName) {
232
+ try {
233
+ const result = await backend.queryProcesses(repoName, 50);
234
+ if (!result.processes || result.processes.length === 0) {
235
+ return 'processes: []\n# No processes detected. Run: gitnexus analyze';
236
+ }
237
+ const displayLimit = 20;
238
+ const lines = ['processes:'];
239
+ const toShow = result.processes.slice(0, displayLimit);
240
+ for (const proc of toShow) {
241
+ const label = proc.heuristicLabel || proc.label || proc.id;
242
+ lines.push(` - name: "${label}"`);
243
+ lines.push(` type: ${proc.processType || 'unknown'}`);
244
+ lines.push(` steps: ${proc.stepCount || 0}`);
245
+ }
246
+ if (result.processes.length > displayLimit) {
247
+ lines.push(`\n# Showing top ${displayLimit} of ${result.processes.length} processes. Use gitnexus_query for deeper search.`);
248
+ }
249
+ return lines.join('\n');
250
+ }
251
+ catch (err) {
252
+ return `error: ${err.message}`;
253
+ }
254
+ }
255
+ /**
256
+ * Schema resource — graph structure for Cypher queries
257
+ */
258
+ function getSchemaResource() {
259
+ return `# GitNexus Graph Schema
260
+
261
+ nodes:
262
+ - File: Source code files
263
+ - Folder: Directory containers
264
+ - Function: Functions and arrow functions
265
+ - Class: Class definitions
266
+ - Interface: Interface/type definitions
267
+ - Method: Class methods
268
+ - CodeElement: Catch-all for other code elements
269
+ - Community: Auto-detected functional area (Leiden algorithm)
270
+ - Process: Execution flow trace
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
+
274
+ relationships:
275
+ - CONTAINS: File/Folder contains child
276
+ - DEFINES: File defines a symbol
277
+ - CALLS: Function/method invocation
278
+ - IMPORTS: Module imports
279
+ - EXTENDS: Class inheritance
280
+ - IMPLEMENTS: Interface implementation
281
+ - HAS_METHOD: Class/Struct/Interface owns a Method
282
+ - HAS_PROPERTY: Class/Struct/Interface owns a Property (field)
283
+ - ACCESSES: Function/Method reads or writes a Property (reason: 'read' or 'write')
284
+ - OVERRIDES: Method overrides another Method (MRO)
285
+ - MEMBER_OF: Symbol belongs to community
286
+ - STEP_IN_PROCESS: Symbol is step N in process
287
+
288
+ relationship_table: "All relationships use a single CodeRelation table with a 'type' property. Properties: type (STRING), confidence (DOUBLE), reason (STRING), step (INT32)"
289
+
290
+ example_queries:
291
+ find_callers: |
292
+ MATCH (caller)-[:CodeRelation {type: 'CALLS'}]->(f:Function {name: "myFunc"})
293
+ RETURN caller.name, caller.filePath
294
+
295
+ find_community_members: |
296
+ MATCH (s)-[:CodeRelation {type: 'MEMBER_OF'}]->(c:Community)
297
+ WHERE c.heuristicLabel = "Auth"
298
+ RETURN s.name, labels(s)[0] AS type
299
+
300
+ trace_process: |
301
+ MATCH (s)-[r:CodeRelation {type: 'STEP_IN_PROCESS'}]->(p:Process)
302
+ WHERE p.heuristicLabel = "LoginFlow"
303
+ RETURN s.name, r.step
304
+ ORDER BY r.step
305
+ `;
306
+ }
307
+ /**
308
+ * Cluster detail resource — queries graph directly via backend.queryClusterDetail()
309
+ */
310
+ async function getClusterDetailResource(name, backend, repoName) {
311
+ try {
312
+ const result = await backend.queryClusterDetail(name, repoName);
313
+ if (result.error) {
314
+ return `error: ${result.error}`;
315
+ }
316
+ const cluster = result.cluster;
317
+ const members = result.members || [];
318
+ const lines = [
319
+ `module: "${cluster.heuristicLabel || cluster.label || cluster.id}"`,
320
+ `symbols: ${cluster.symbolCount || members.length}`,
321
+ ];
322
+ if (cluster.cohesion) {
323
+ lines.push(`cohesion: ${(cluster.cohesion * 100).toFixed(0)}%`);
324
+ }
325
+ if (members.length > 0) {
326
+ lines.push('');
327
+ lines.push('members:');
328
+ for (const member of members.slice(0, 20)) {
329
+ lines.push(` - name: ${member.name}`);
330
+ lines.push(` type: ${member.type}`);
331
+ lines.push(` file: ${member.filePath}`);
332
+ }
333
+ if (members.length > 20) {
334
+ lines.push(` # ... and ${members.length - 20} more`);
335
+ }
336
+ }
337
+ return lines.join('\n');
338
+ }
339
+ catch (err) {
340
+ return `error: ${err.message}`;
341
+ }
342
+ }
343
+ /**
344
+ * Process detail resource — queries graph directly via backend.queryProcessDetail()
345
+ */
346
+ async function getProcessDetailResource(name, backend, repoName) {
347
+ try {
348
+ const result = await backend.queryProcessDetail(name, repoName);
349
+ if (result.error) {
350
+ return `error: ${result.error}`;
351
+ }
352
+ const proc = result.process;
353
+ const steps = result.steps || [];
354
+ const lines = [
355
+ `name: "${proc.heuristicLabel || proc.label || proc.id}"`,
356
+ `type: ${proc.processType || 'unknown'}`,
357
+ `step_count: ${proc.stepCount || steps.length}`,
358
+ ];
359
+ if (steps.length > 0) {
360
+ lines.push('');
361
+ lines.push('trace:');
362
+ for (const step of steps) {
363
+ lines.push(` ${step.step}: ${step.name} (${step.filePath})`);
364
+ }
365
+ }
366
+ return lines.join('\n');
367
+ }
368
+ catch (err) {
369
+ return `error: ${err.message}`;
370
+ }
371
+ }
372
+ /**
373
+ * Setup resource — generates AGENTS.md content for all indexed repos.
374
+ * Useful for `gitnexus setup` onboarding or dynamic content injection.
375
+ */
376
+ async function getSetupResource(backend) {
377
+ const repos = await backend.listRepos();
378
+ if (repos.length === 0) {
379
+ return '# GitNexus\n\nNo repositories indexed. Run: `npx gitnexus analyze` in a repository.';
380
+ }
381
+ const sections = [];
382
+ for (const repo of repos) {
383
+ const stats = repo.stats || {};
384
+ const lines = [
385
+ `# GitNexus MCP — ${repo.name}`,
386
+ '',
387
+ `This project is indexed by GitNexus as **${repo.name}** (${stats.nodes || 0} symbols, ${stats.edges || 0} relationships, ${stats.processes || 0} execution flows).`,
388
+ '',
389
+ '## Tools',
390
+ '',
391
+ '| Tool | What it gives you |',
392
+ '|------|-------------------|',
393
+ '| `query` | Process-grouped code intelligence — execution flows related to a concept |',
394
+ '| `context` | 360-degree symbol view — categorized refs, processes it participates in |',
395
+ '| `impact` | Symbol blast radius — what breaks at depth 1/2/3 with confidence |',
396
+ '| `detect_changes` | Git-diff impact — what do your current changes affect |',
397
+ '| `rename` | Multi-file coordinated rename with confidence-tagged edits |',
398
+ '| `cypher` | Raw graph queries |',
399
+ '| `list_repos` | Discover indexed repos |',
400
+ '',
401
+ '## Resources',
402
+ '',
403
+ `- \`gitnexus://repo/${repo.name}/context\` — Stats, staleness check`,
404
+ `- \`gitnexus://repo/${repo.name}/clusters\` — All functional areas`,
405
+ `- \`gitnexus://repo/${repo.name}/processes\` — All execution flows`,
406
+ `- \`gitnexus://repo/${repo.name}/schema\` — Graph schema for Cypher`,
407
+ ];
408
+ sections.push(lines.join('\n'));
409
+ }
410
+ return sections.join('\n\n---\n\n');
411
+ }
@@ -0,0 +1,23 @@
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 type { LocalBackend } from './local/local-backend.js';
15
+ /**
16
+ * Create a configured MCP Server with all handlers registered.
17
+ * Transport-agnostic — caller connects the desired transport.
18
+ */
19
+ export declare function createMCPServer(backend: LocalBackend): Server;
20
+ /**
21
+ * Start the MCP server on stdio transport (for CLI use).
22
+ */
23
+ export declare function startMCPServer(backend: LocalBackend): Promise<void>;