bluera-knowledge 0.9.32 → 0.9.34

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 (196) hide show
  1. package/.claude/hooks/post-edit-check.sh +5 -3
  2. package/.claude/skills/atomic-commits/SKILL.md +3 -1
  3. package/.husky/pre-commit +3 -2
  4. package/.prettierrc +9 -0
  5. package/.versionrc.json +1 -1
  6. package/CHANGELOG.md +33 -0
  7. package/CLAUDE.md +6 -0
  8. package/README.md +25 -13
  9. package/bun.lock +277 -33
  10. package/dist/{chunk-L2YVNC63.js → chunk-6FHWC36B.js} +9 -1
  11. package/dist/chunk-6FHWC36B.js.map +1 -0
  12. package/dist/{chunk-RST4XGRL.js → chunk-DC7CGSGT.js} +288 -241
  13. package/dist/chunk-DC7CGSGT.js.map +1 -0
  14. package/dist/{chunk-6PBP5DVD.js → chunk-WFNPNAAP.js} +3212 -3054
  15. package/dist/chunk-WFNPNAAP.js.map +1 -0
  16. package/dist/{chunk-WT2DAEO7.js → chunk-Z2KKVH45.js} +548 -482
  17. package/dist/chunk-Z2KKVH45.js.map +1 -0
  18. package/dist/index.js +871 -758
  19. package/dist/index.js.map +1 -1
  20. package/dist/mcp/server.js +3 -3
  21. package/dist/watch.service-BJV3TI3F.js +7 -0
  22. package/dist/workers/background-worker-cli.js +46 -45
  23. package/dist/workers/background-worker-cli.js.map +1 -1
  24. package/eslint.config.js +43 -1
  25. package/package.json +18 -11
  26. package/plugin.json +8 -0
  27. package/python/requirements.txt +1 -1
  28. package/src/analysis/ast-parser.test.ts +12 -11
  29. package/src/analysis/ast-parser.ts +28 -22
  30. package/src/analysis/code-graph.test.ts +52 -62
  31. package/src/analysis/code-graph.ts +9 -13
  32. package/src/analysis/dependency-usage-analyzer.test.ts +91 -271
  33. package/src/analysis/dependency-usage-analyzer.ts +52 -24
  34. package/src/analysis/go-ast-parser.test.ts +22 -22
  35. package/src/analysis/go-ast-parser.ts +18 -25
  36. package/src/analysis/parser-factory.test.ts +9 -9
  37. package/src/analysis/parser-factory.ts +3 -3
  38. package/src/analysis/python-ast-parser.test.ts +27 -27
  39. package/src/analysis/python-ast-parser.ts +2 -2
  40. package/src/analysis/repo-url-resolver.test.ts +82 -82
  41. package/src/analysis/rust-ast-parser.test.ts +19 -19
  42. package/src/analysis/rust-ast-parser.ts +17 -27
  43. package/src/analysis/tree-sitter-parser.test.ts +3 -3
  44. package/src/analysis/tree-sitter-parser.ts +10 -16
  45. package/src/cli/commands/crawl.test.ts +40 -24
  46. package/src/cli/commands/crawl.ts +186 -166
  47. package/src/cli/commands/index-cmd.test.ts +90 -90
  48. package/src/cli/commands/index-cmd.ts +52 -36
  49. package/src/cli/commands/mcp.test.ts +6 -6
  50. package/src/cli/commands/mcp.ts +2 -2
  51. package/src/cli/commands/plugin-api.test.ts +16 -18
  52. package/src/cli/commands/plugin-api.ts +9 -6
  53. package/src/cli/commands/search.test.ts +16 -7
  54. package/src/cli/commands/search.ts +124 -87
  55. package/src/cli/commands/serve.test.ts +67 -25
  56. package/src/cli/commands/serve.ts +18 -3
  57. package/src/cli/commands/setup.test.ts +176 -101
  58. package/src/cli/commands/setup.ts +140 -117
  59. package/src/cli/commands/store.test.ts +82 -53
  60. package/src/cli/commands/store.ts +56 -37
  61. package/src/cli/program.ts +2 -2
  62. package/src/crawl/article-converter.test.ts +4 -1
  63. package/src/crawl/article-converter.ts +46 -31
  64. package/src/crawl/bridge.test.ts +240 -132
  65. package/src/crawl/bridge.ts +87 -30
  66. package/src/crawl/claude-client.test.ts +124 -56
  67. package/src/crawl/claude-client.ts +7 -15
  68. package/src/crawl/intelligent-crawler.test.ts +65 -22
  69. package/src/crawl/intelligent-crawler.ts +86 -53
  70. package/src/crawl/markdown-utils.ts +1 -4
  71. package/src/db/embeddings.ts +4 -6
  72. package/src/db/lance.test.ts +4 -4
  73. package/src/db/lance.ts +16 -12
  74. package/src/index.ts +26 -17
  75. package/src/logging/index.ts +1 -5
  76. package/src/logging/logger.ts +3 -5
  77. package/src/logging/payload.test.ts +1 -1
  78. package/src/logging/payload.ts +3 -5
  79. package/src/mcp/commands/index.ts +2 -2
  80. package/src/mcp/commands/job.commands.ts +12 -18
  81. package/src/mcp/commands/meta.commands.ts +13 -13
  82. package/src/mcp/commands/registry.ts +5 -8
  83. package/src/mcp/commands/store.commands.ts +19 -19
  84. package/src/mcp/handlers/execute.handler.test.ts +10 -10
  85. package/src/mcp/handlers/execute.handler.ts +4 -5
  86. package/src/mcp/handlers/index.ts +10 -14
  87. package/src/mcp/handlers/job.handler.test.ts +10 -10
  88. package/src/mcp/handlers/job.handler.ts +22 -25
  89. package/src/mcp/handlers/search.handler.test.ts +36 -65
  90. package/src/mcp/handlers/search.handler.ts +135 -104
  91. package/src/mcp/handlers/store.handler.test.ts +41 -52
  92. package/src/mcp/handlers/store.handler.ts +108 -88
  93. package/src/mcp/schemas/index.test.ts +73 -68
  94. package/src/mcp/schemas/index.ts +18 -12
  95. package/src/mcp/server.test.ts +1 -1
  96. package/src/mcp/server.ts +59 -46
  97. package/src/plugin/commands.test.ts +230 -95
  98. package/src/plugin/commands.ts +24 -25
  99. package/src/plugin/dependency-analyzer.test.ts +52 -52
  100. package/src/plugin/dependency-analyzer.ts +85 -22
  101. package/src/plugin/git-clone.test.ts +24 -13
  102. package/src/plugin/git-clone.ts +3 -7
  103. package/src/server/app.test.ts +109 -109
  104. package/src/server/app.ts +32 -23
  105. package/src/server/index.test.ts +64 -66
  106. package/src/services/chunking.service.test.ts +32 -32
  107. package/src/services/chunking.service.ts +16 -9
  108. package/src/services/code-graph.service.test.ts +30 -36
  109. package/src/services/code-graph.service.ts +24 -10
  110. package/src/services/code-unit.service.test.ts +55 -11
  111. package/src/services/code-unit.service.ts +85 -11
  112. package/src/services/config.service.test.ts +37 -18
  113. package/src/services/config.service.ts +30 -7
  114. package/src/services/index.service.test.ts +49 -18
  115. package/src/services/index.service.ts +98 -48
  116. package/src/services/index.ts +6 -9
  117. package/src/services/job.service.test.ts +22 -22
  118. package/src/services/job.service.ts +18 -18
  119. package/src/services/project-root.service.test.ts +1 -3
  120. package/src/services/search.service.test.ts +248 -120
  121. package/src/services/search.service.ts +286 -156
  122. package/src/services/services.test.ts +1 -1
  123. package/src/services/snippet.service.test.ts +14 -6
  124. package/src/services/snippet.service.ts +7 -5
  125. package/src/services/store.service.test.ts +68 -29
  126. package/src/services/store.service.ts +41 -12
  127. package/src/services/watch.service.test.ts +34 -14
  128. package/src/services/watch.service.ts +11 -1
  129. package/src/types/brands.test.ts +3 -1
  130. package/src/types/index.ts +2 -13
  131. package/src/types/search.ts +10 -8
  132. package/src/utils/type-guards.test.ts +20 -15
  133. package/src/utils/type-guards.ts +1 -1
  134. package/src/workers/background-worker-cli.ts +2 -2
  135. package/src/workers/background-worker.test.ts +54 -40
  136. package/src/workers/background-worker.ts +76 -60
  137. package/src/workers/spawn-worker.test.ts +22 -10
  138. package/src/workers/spawn-worker.ts +6 -6
  139. package/tests/analysis/ast-parser.test.ts +3 -3
  140. package/tests/analysis/code-graph.test.ts +5 -5
  141. package/tests/fixtures/code-snippets/api/error-handling.ts +4 -15
  142. package/tests/fixtures/code-snippets/api/rest-controller.ts +3 -9
  143. package/tests/fixtures/code-snippets/auth/jwt-auth.ts +5 -21
  144. package/tests/fixtures/code-snippets/auth/oauth-flow.ts +4 -4
  145. package/tests/fixtures/code-snippets/database/repository-pattern.ts +11 -3
  146. package/tests/fixtures/corpus/oss-repos/hono/src/adapter/aws-lambda/handler.ts +2 -2
  147. package/tests/fixtures/corpus/oss-repos/hono/src/adapter/cloudflare-pages/handler.ts +1 -1
  148. package/tests/fixtures/corpus/oss-repos/hono/src/adapter/cloudflare-workers/serve-static.ts +2 -2
  149. package/tests/fixtures/corpus/oss-repos/hono/src/client/client.ts +2 -2
  150. package/tests/fixtures/corpus/oss-repos/hono/src/client/types.ts +22 -20
  151. package/tests/fixtures/corpus/oss-repos/hono/src/context.ts +13 -10
  152. package/tests/fixtures/corpus/oss-repos/hono/src/helper/accepts/accepts.ts +10 -7
  153. package/tests/fixtures/corpus/oss-repos/hono/src/helper/adapter/index.ts +2 -2
  154. package/tests/fixtures/corpus/oss-repos/hono/src/helper/css/index.ts +1 -1
  155. package/tests/fixtures/corpus/oss-repos/hono/src/helper/factory/index.ts +16 -16
  156. package/tests/fixtures/corpus/oss-repos/hono/src/helper/ssg/ssg.ts +2 -2
  157. package/tests/fixtures/corpus/oss-repos/hono/src/hono-base.ts +3 -3
  158. package/tests/fixtures/corpus/oss-repos/hono/src/hono.ts +1 -1
  159. package/tests/fixtures/corpus/oss-repos/hono/src/jsx/dom/css.ts +2 -2
  160. package/tests/fixtures/corpus/oss-repos/hono/src/jsx/dom/intrinsic-element/components.ts +1 -1
  161. package/tests/fixtures/corpus/oss-repos/hono/src/jsx/dom/render.ts +7 -7
  162. package/tests/fixtures/corpus/oss-repos/hono/src/jsx/hooks/index.ts +3 -3
  163. package/tests/fixtures/corpus/oss-repos/hono/src/jsx/intrinsic-element/components.ts +1 -1
  164. package/tests/fixtures/corpus/oss-repos/hono/src/jsx/utils.ts +6 -6
  165. package/tests/fixtures/corpus/oss-repos/hono/src/middleware/jsx-renderer/index.ts +3 -3
  166. package/tests/fixtures/corpus/oss-repos/hono/src/middleware/serve-static/index.ts +1 -1
  167. package/tests/fixtures/corpus/oss-repos/hono/src/preset/quick.ts +1 -1
  168. package/tests/fixtures/corpus/oss-repos/hono/src/preset/tiny.ts +1 -1
  169. package/tests/fixtures/corpus/oss-repos/hono/src/router/pattern-router/router.ts +2 -2
  170. package/tests/fixtures/corpus/oss-repos/hono/src/router/reg-exp-router/node.ts +4 -4
  171. package/tests/fixtures/corpus/oss-repos/hono/src/router/reg-exp-router/router.ts +1 -1
  172. package/tests/fixtures/corpus/oss-repos/hono/src/router/trie-router/node.ts +1 -1
  173. package/tests/fixtures/corpus/oss-repos/hono/src/types.ts +166 -169
  174. package/tests/fixtures/corpus/oss-repos/hono/src/utils/body.ts +8 -8
  175. package/tests/fixtures/corpus/oss-repos/hono/src/utils/color.ts +3 -3
  176. package/tests/fixtures/corpus/oss-repos/hono/src/utils/cookie.ts +2 -2
  177. package/tests/fixtures/corpus/oss-repos/hono/src/utils/encode.ts +2 -2
  178. package/tests/fixtures/corpus/oss-repos/hono/src/utils/types.ts +30 -33
  179. package/tests/fixtures/corpus/oss-repos/hono/src/validator/validator.ts +2 -2
  180. package/tests/fixtures/test-server.ts +3 -2
  181. package/tests/helpers/performance-metrics.ts +8 -25
  182. package/tests/helpers/search-relevance.ts +14 -69
  183. package/tests/integration/cli-consistency.test.ts +5 -4
  184. package/tests/integration/python-bridge.test.ts +13 -3
  185. package/tests/mcp/server.test.ts +1 -1
  186. package/tests/services/code-unit.service.test.ts +48 -0
  187. package/tests/services/job.service.test.ts +124 -0
  188. package/tests/services/search.progressive-context.test.ts +2 -2
  189. package/.claude-plugin/plugin.json +0 -13
  190. package/dist/chunk-6PBP5DVD.js.map +0 -1
  191. package/dist/chunk-L2YVNC63.js.map +0 -1
  192. package/dist/chunk-RST4XGRL.js.map +0 -1
  193. package/dist/chunk-WT2DAEO7.js.map +0 -1
  194. package/dist/watch.service-YAIKKDCF.js +0 -7
  195. package/skills/atomic-commits/SKILL.md +0 -77
  196. /package/dist/{watch.service-YAIKKDCF.js.map → watch.service-BJV3TI3F.js.map} +0 -0
@@ -9,7 +9,7 @@ import {
9
9
  DeleteStoreArgsSchema,
10
10
  CheckJobStatusArgsSchema,
11
11
  ListJobsArgsSchema,
12
- CancelJobArgsSchema
12
+ CancelJobArgsSchema,
13
13
  } from './index.js';
14
14
 
15
15
  describe('MCP Schema Validation', () => {
@@ -18,7 +18,7 @@ describe('MCP Schema Validation', () => {
18
18
  const result = SearchArgsSchema.parse({
19
19
  query: 'test query',
20
20
  detail: 'minimal',
21
- limit: 10
21
+ limit: 10,
22
22
  });
23
23
 
24
24
  expect(result.query).toBe('test query');
@@ -34,13 +34,13 @@ describe('MCP Schema Validation', () => {
34
34
  });
35
35
 
36
36
  it('should reject empty query', () => {
37
- expect(() => SearchArgsSchema.parse({ query: '' }))
38
- .toThrow('Query must be a non-empty string');
37
+ expect(() => SearchArgsSchema.parse({ query: '' })).toThrow(
38
+ 'Query must be a non-empty string'
39
+ );
39
40
  });
40
41
 
41
42
  it('should validate detail enum', () => {
42
- expect(() => SearchArgsSchema.parse({ query: 'test', detail: 'invalid' }))
43
- .toThrow();
43
+ expect(() => SearchArgsSchema.parse({ query: 'test', detail: 'invalid' })).toThrow();
44
44
 
45
45
  const minimal = SearchArgsSchema.parse({ query: 'test', detail: 'minimal' });
46
46
  expect(minimal.detail).toBe('minimal');
@@ -55,7 +55,7 @@ describe('MCP Schema Validation', () => {
55
55
  it('should validate intent enum', () => {
56
56
  const result = SearchArgsSchema.parse({
57
57
  query: 'test',
58
- intent: 'find-implementation'
58
+ intent: 'find-implementation',
59
59
  });
60
60
 
61
61
  expect(result.intent).toBe('find-implementation');
@@ -64,21 +64,18 @@ describe('MCP Schema Validation', () => {
64
64
  it('should validate stores array', () => {
65
65
  const result = SearchArgsSchema.parse({
66
66
  query: 'test',
67
- stores: ['store1', 'store2']
67
+ stores: ['store1', 'store2'],
68
68
  });
69
69
 
70
70
  expect(result.stores).toEqual(['store1', 'store2']);
71
71
  });
72
72
 
73
73
  it('should reject invalid limit', () => {
74
- expect(() => SearchArgsSchema.parse({ query: 'test', limit: -1 }))
75
- .toThrow();
74
+ expect(() => SearchArgsSchema.parse({ query: 'test', limit: -1 })).toThrow();
76
75
 
77
- expect(() => SearchArgsSchema.parse({ query: 'test', limit: 0 }))
78
- .toThrow();
76
+ expect(() => SearchArgsSchema.parse({ query: 'test', limit: 0 })).toThrow();
79
77
 
80
- expect(() => SearchArgsSchema.parse({ query: 'test', limit: 1.5 }))
81
- .toThrow();
78
+ expect(() => SearchArgsSchema.parse({ query: 'test', limit: 1.5 })).toThrow();
82
79
  });
83
80
  });
84
81
 
@@ -89,13 +86,13 @@ describe('MCP Schema Validation', () => {
89
86
  });
90
87
 
91
88
  it('should reject empty resultId', () => {
92
- expect(() => GetFullContextArgsSchema.parse({ resultId: '' }))
93
- .toThrow('Result ID must be a non-empty string');
89
+ expect(() => GetFullContextArgsSchema.parse({ resultId: '' })).toThrow(
90
+ 'Result ID must be a non-empty string'
91
+ );
94
92
  });
95
93
 
96
94
  it('should reject missing resultId', () => {
97
- expect(() => GetFullContextArgsSchema.parse({}))
98
- .toThrow();
95
+ expect(() => GetFullContextArgsSchema.parse({})).toThrow();
99
96
  });
100
97
  });
101
98
 
@@ -117,8 +114,7 @@ describe('MCP Schema Validation', () => {
117
114
  });
118
115
 
119
116
  it('should reject invalid type', () => {
120
- expect(() => ListStoresArgsSchema.parse({ type: 'invalid' }))
121
- .toThrow();
117
+ expect(() => ListStoresArgsSchema.parse({ type: 'invalid' })).toThrow();
122
118
  });
123
119
  });
124
120
 
@@ -129,13 +125,13 @@ describe('MCP Schema Validation', () => {
129
125
  });
130
126
 
131
127
  it('should reject empty store', () => {
132
- expect(() => GetStoreInfoArgsSchema.parse({ store: '' }))
133
- .toThrow('Store name or ID must be a non-empty string');
128
+ expect(() => GetStoreInfoArgsSchema.parse({ store: '' })).toThrow(
129
+ 'Store name or ID must be a non-empty string'
130
+ );
134
131
  });
135
132
 
136
133
  it('should reject missing store', () => {
137
- expect(() => GetStoreInfoArgsSchema.parse({}))
138
- .toThrow();
134
+ expect(() => GetStoreInfoArgsSchema.parse({})).toThrow();
139
135
  });
140
136
  });
141
137
 
@@ -144,7 +140,7 @@ describe('MCP Schema Validation', () => {
144
140
  const result = CreateStoreArgsSchema.parse({
145
141
  name: 'test-store',
146
142
  type: 'file',
147
- source: '/path/to/source'
143
+ source: '/path/to/source',
148
144
  });
149
145
 
150
146
  expect(result.name).toBe('test-store');
@@ -158,7 +154,7 @@ describe('MCP Schema Validation', () => {
158
154
  type: 'repo',
159
155
  source: 'https://github.com/test/repo',
160
156
  branch: 'main',
161
- description: 'Test repository'
157
+ description: 'Test repository',
162
158
  });
163
159
 
164
160
  expect(result.name).toBe('test-repo');
@@ -169,36 +165,46 @@ describe('MCP Schema Validation', () => {
169
165
  });
170
166
 
171
167
  it('should reject empty name', () => {
172
- expect(() => CreateStoreArgsSchema.parse({
173
- name: '',
174
- type: 'file',
175
- source: '/path'
176
- })).toThrow('Store name must be a non-empty string');
168
+ expect(() =>
169
+ CreateStoreArgsSchema.parse({
170
+ name: '',
171
+ type: 'file',
172
+ source: '/path',
173
+ })
174
+ ).toThrow('Store name must be a non-empty string');
177
175
  });
178
176
 
179
177
  it('should reject invalid type', () => {
180
- expect(() => CreateStoreArgsSchema.parse({
181
- name: 'test',
182
- type: 'invalid',
183
- source: '/path'
184
- })).toThrow();
178
+ expect(() =>
179
+ CreateStoreArgsSchema.parse({
180
+ name: 'test',
181
+ type: 'invalid',
182
+ source: '/path',
183
+ })
184
+ ).toThrow();
185
185
  });
186
186
 
187
187
  it('should reject missing required fields', () => {
188
- expect(() => CreateStoreArgsSchema.parse({
189
- name: 'test',
190
- type: 'file'
191
- })).toThrow();
192
-
193
- expect(() => CreateStoreArgsSchema.parse({
194
- name: 'test',
195
- source: '/path'
196
- })).toThrow();
197
-
198
- expect(() => CreateStoreArgsSchema.parse({
199
- type: 'file',
200
- source: '/path'
201
- })).toThrow();
188
+ expect(() =>
189
+ CreateStoreArgsSchema.parse({
190
+ name: 'test',
191
+ type: 'file',
192
+ })
193
+ ).toThrow();
194
+
195
+ expect(() =>
196
+ CreateStoreArgsSchema.parse({
197
+ name: 'test',
198
+ source: '/path',
199
+ })
200
+ ).toThrow();
201
+
202
+ expect(() =>
203
+ CreateStoreArgsSchema.parse({
204
+ type: 'file',
205
+ source: '/path',
206
+ })
207
+ ).toThrow();
202
208
  });
203
209
  });
204
210
 
@@ -209,13 +215,13 @@ describe('MCP Schema Validation', () => {
209
215
  });
210
216
 
211
217
  it('should reject empty store', () => {
212
- expect(() => IndexStoreArgsSchema.parse({ store: '' }))
213
- .toThrow('Store name or ID must be a non-empty string');
218
+ expect(() => IndexStoreArgsSchema.parse({ store: '' })).toThrow(
219
+ 'Store name or ID must be a non-empty string'
220
+ );
214
221
  });
215
222
 
216
223
  it('should reject missing store', () => {
217
- expect(() => IndexStoreArgsSchema.parse({}))
218
- .toThrow();
224
+ expect(() => IndexStoreArgsSchema.parse({})).toThrow();
219
225
  });
220
226
  });
221
227
 
@@ -231,13 +237,13 @@ describe('MCP Schema Validation', () => {
231
237
  });
232
238
 
233
239
  it('should reject empty store', () => {
234
- expect(() => DeleteStoreArgsSchema.parse({ store: '' }))
235
- .toThrow('Store name or ID must be a non-empty string');
240
+ expect(() => DeleteStoreArgsSchema.parse({ store: '' })).toThrow(
241
+ 'Store name or ID must be a non-empty string'
242
+ );
236
243
  });
237
244
 
238
245
  it('should reject missing store', () => {
239
- expect(() => DeleteStoreArgsSchema.parse({}))
240
- .toThrow();
246
+ expect(() => DeleteStoreArgsSchema.parse({})).toThrow();
241
247
  });
242
248
  });
243
249
 
@@ -248,13 +254,13 @@ describe('MCP Schema Validation', () => {
248
254
  });
249
255
 
250
256
  it('should reject empty jobId', () => {
251
- expect(() => CheckJobStatusArgsSchema.parse({ jobId: '' }))
252
- .toThrow('Job ID must be a non-empty string');
257
+ expect(() => CheckJobStatusArgsSchema.parse({ jobId: '' })).toThrow(
258
+ 'Job ID must be a non-empty string'
259
+ );
253
260
  });
254
261
 
255
262
  it('should reject missing jobId', () => {
256
- expect(() => CheckJobStatusArgsSchema.parse({}))
257
- .toThrow();
263
+ expect(() => CheckJobStatusArgsSchema.parse({})).toThrow();
258
264
  });
259
265
  });
260
266
 
@@ -291,8 +297,7 @@ describe('MCP Schema Validation', () => {
291
297
  });
292
298
 
293
299
  it('should reject invalid status', () => {
294
- expect(() => ListJobsArgsSchema.parse({ status: 'invalid' }))
295
- .toThrow();
300
+ expect(() => ListJobsArgsSchema.parse({ status: 'invalid' })).toThrow();
296
301
  });
297
302
  });
298
303
 
@@ -303,13 +308,13 @@ describe('MCP Schema Validation', () => {
303
308
  });
304
309
 
305
310
  it('should reject empty jobId', () => {
306
- expect(() => CancelJobArgsSchema.parse({ jobId: '' }))
307
- .toThrow('Job ID must be a non-empty string');
311
+ expect(() => CancelJobArgsSchema.parse({ jobId: '' })).toThrow(
312
+ 'Job ID must be a non-empty string'
313
+ );
308
314
  });
309
315
 
310
316
  it('should reject missing jobId', () => {
311
- expect(() => CancelJobArgsSchema.parse({}))
312
- .toThrow();
317
+ expect(() => CancelJobArgsSchema.parse({})).toThrow();
313
318
  });
314
319
  });
315
320
  });
@@ -17,11 +17,17 @@ import { z } from 'zod';
17
17
  export const SearchArgsSchema = z.object({
18
18
  query: z.string().min(1, 'Query must be a non-empty string'),
19
19
  intent: z
20
- .enum(['find-pattern', 'find-implementation', 'find-usage', 'find-definition', 'find-documentation'])
20
+ .enum([
21
+ 'find-pattern',
22
+ 'find-implementation',
23
+ 'find-usage',
24
+ 'find-definition',
25
+ 'find-documentation',
26
+ ])
21
27
  .optional(),
22
28
  detail: z.enum(['minimal', 'contextual', 'full']).default('minimal'),
23
29
  limit: z.number().int().positive().default(10),
24
- stores: z.array(z.string()).optional()
30
+ stores: z.array(z.string()).optional(),
25
31
  });
26
32
 
27
33
  export type SearchArgs = z.infer<typeof SearchArgsSchema>;
@@ -30,7 +36,7 @@ export type SearchArgs = z.infer<typeof SearchArgsSchema>;
30
36
  * Schema for get_full_context tool arguments
31
37
  */
32
38
  export const GetFullContextArgsSchema = z.object({
33
- resultId: z.string().min(1, 'Result ID must be a non-empty string')
39
+ resultId: z.string().min(1, 'Result ID must be a non-empty string'),
34
40
  });
35
41
 
36
42
  export type GetFullContextArgs = z.infer<typeof GetFullContextArgsSchema>;
@@ -43,7 +49,7 @@ export type GetFullContextArgs = z.infer<typeof GetFullContextArgsSchema>;
43
49
  * Schema for list_stores tool arguments
44
50
  */
45
51
  export const ListStoresArgsSchema = z.object({
46
- type: z.enum(['file', 'repo', 'web']).optional()
52
+ type: z.enum(['file', 'repo', 'web']).optional(),
47
53
  });
48
54
 
49
55
  export type ListStoresArgs = z.infer<typeof ListStoresArgsSchema>;
@@ -52,7 +58,7 @@ export type ListStoresArgs = z.infer<typeof ListStoresArgsSchema>;
52
58
  * Schema for get_store_info tool arguments
53
59
  */
54
60
  export const GetStoreInfoArgsSchema = z.object({
55
- store: z.string().min(1, 'Store name or ID must be a non-empty string')
61
+ store: z.string().min(1, 'Store name or ID must be a non-empty string'),
56
62
  });
57
63
 
58
64
  export type GetStoreInfoArgs = z.infer<typeof GetStoreInfoArgsSchema>;
@@ -65,7 +71,7 @@ export const CreateStoreArgsSchema = z.object({
65
71
  type: z.enum(['file', 'repo']),
66
72
  source: z.string().min(1, 'Source path or URL must be a non-empty string'),
67
73
  branch: z.string().optional(),
68
- description: z.string().optional()
74
+ description: z.string().optional(),
69
75
  });
70
76
 
71
77
  export type CreateStoreArgs = z.infer<typeof CreateStoreArgsSchema>;
@@ -74,7 +80,7 @@ export type CreateStoreArgs = z.infer<typeof CreateStoreArgsSchema>;
74
80
  * Schema for index_store tool arguments
75
81
  */
76
82
  export const IndexStoreArgsSchema = z.object({
77
- store: z.string().min(1, 'Store name or ID must be a non-empty string')
83
+ store: z.string().min(1, 'Store name or ID must be a non-empty string'),
78
84
  });
79
85
 
80
86
  export type IndexStoreArgs = z.infer<typeof IndexStoreArgsSchema>;
@@ -83,7 +89,7 @@ export type IndexStoreArgs = z.infer<typeof IndexStoreArgsSchema>;
83
89
  * Schema for delete_store tool arguments
84
90
  */
85
91
  export const DeleteStoreArgsSchema = z.object({
86
- store: z.string().min(1, 'Store name or ID must be a non-empty string')
92
+ store: z.string().min(1, 'Store name or ID must be a non-empty string'),
87
93
  });
88
94
 
89
95
  export type DeleteStoreArgs = z.infer<typeof DeleteStoreArgsSchema>;
@@ -96,7 +102,7 @@ export type DeleteStoreArgs = z.infer<typeof DeleteStoreArgsSchema>;
96
102
  * Schema for check_job_status tool arguments
97
103
  */
98
104
  export const CheckJobStatusArgsSchema = z.object({
99
- jobId: z.string().min(1, 'Job ID must be a non-empty string')
105
+ jobId: z.string().min(1, 'Job ID must be a non-empty string'),
100
106
  });
101
107
 
102
108
  export type CheckJobStatusArgs = z.infer<typeof CheckJobStatusArgsSchema>;
@@ -106,7 +112,7 @@ export type CheckJobStatusArgs = z.infer<typeof CheckJobStatusArgsSchema>;
106
112
  */
107
113
  export const ListJobsArgsSchema = z.object({
108
114
  activeOnly: z.boolean().optional(),
109
- status: z.enum(['pending', 'running', 'completed', 'failed', 'cancelled']).optional()
115
+ status: z.enum(['pending', 'running', 'completed', 'failed', 'cancelled']).optional(),
110
116
  });
111
117
 
112
118
  export type ListJobsArgs = z.infer<typeof ListJobsArgsSchema>;
@@ -115,7 +121,7 @@ export type ListJobsArgs = z.infer<typeof ListJobsArgsSchema>;
115
121
  * Schema for cancel_job tool arguments
116
122
  */
117
123
  export const CancelJobArgsSchema = z.object({
118
- jobId: z.string().min(1, 'Job ID must be a non-empty string')
124
+ jobId: z.string().min(1, 'Job ID must be a non-empty string'),
119
125
  });
120
126
 
121
127
  export type CancelJobArgs = z.infer<typeof CancelJobArgsSchema>;
@@ -132,7 +138,7 @@ export type CancelJobArgs = z.infer<typeof CancelJobArgsSchema>;
132
138
  */
133
139
  export const ExecuteArgsSchema = z.object({
134
140
  command: z.string().min(1, 'Command name is required'),
135
- args: z.record(z.string(), z.unknown()).optional()
141
+ args: z.record(z.string(), z.unknown()).optional(),
136
142
  });
137
143
 
138
144
  export type ExecuteArgs = z.infer<typeof ExecuteArgsSchema>;
@@ -28,7 +28,7 @@ describe('MCP Server', () => {
28
28
  const server = createMCPServer({
29
29
  dataDir: '/data',
30
30
  config: '/config.json',
31
- projectRoot: '/project'
31
+ projectRoot: '/project',
32
32
  });
33
33
  expect(server).toBeDefined();
34
34
  });
package/src/mcp/server.ts CHANGED
@@ -1,15 +1,12 @@
1
1
  import { Server } from '@modelcontextprotocol/sdk/server/index.js';
2
2
  import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
3
- import {
4
- CallToolRequestSchema,
5
- ListToolsRequestSchema,
6
- } from '@modelcontextprotocol/sdk/types.js';
3
+ import { CallToolRequestSchema, ListToolsRequestSchema } from '@modelcontextprotocol/sdk/types.js';
7
4
  import { createServices } from '../services/index.js';
8
- import { tools } from './handlers/index.js';
9
5
  import { handleExecute } from './handlers/execute.handler.js';
6
+ import { tools } from './handlers/index.js';
10
7
  import { ExecuteArgsSchema } from './schemas/index.js';
11
- import type { MCPServerOptions } from './types.js';
12
8
  import { createLogger } from '../logging/index.js';
9
+ import type { MCPServerOptions } from './types.js';
13
10
 
14
11
  const logger = createLogger('mcp-server');
15
12
 
@@ -35,74 +32,85 @@ export function createMCPServer(options: MCPServerOptions): Server {
35
32
  // Native search tool with full schema (most used, benefits from detailed params)
36
33
  {
37
34
  name: 'search',
38
- description: 'Search all indexed knowledge stores with pattern detection and AI-optimized results. Returns structured code units with progressive context layers.',
35
+ description:
36
+ 'Search all indexed knowledge stores with pattern detection and AI-optimized results. Returns structured code units with progressive context layers.',
39
37
  inputSchema: {
40
38
  type: 'object',
41
39
  properties: {
42
40
  query: {
43
41
  type: 'string',
44
- description: 'Search query (can include type signatures, constraints, or natural language)'
42
+ description:
43
+ 'Search query (can include type signatures, constraints, or natural language)',
45
44
  },
46
45
  intent: {
47
46
  type: 'string',
48
- enum: ['find-pattern', 'find-implementation', 'find-usage', 'find-definition', 'find-documentation'],
49
- description: 'Search intent for better ranking'
47
+ enum: [
48
+ 'find-pattern',
49
+ 'find-implementation',
50
+ 'find-usage',
51
+ 'find-definition',
52
+ 'find-documentation',
53
+ ],
54
+ description: 'Search intent for better ranking',
50
55
  },
51
56
  detail: {
52
57
  type: 'string',
53
58
  enum: ['minimal', 'contextual', 'full'],
54
59
  default: 'minimal',
55
- description: 'Context detail level: minimal (summary only), contextual (+ imports/types), full (+ complete code)'
60
+ description:
61
+ 'Context detail level: minimal (summary only), contextual (+ imports/types), full (+ complete code)',
56
62
  },
57
63
  limit: {
58
64
  type: 'number',
59
65
  default: 10,
60
- description: 'Maximum number of results'
66
+ description: 'Maximum number of results',
61
67
  },
62
68
  stores: {
63
69
  type: 'array',
64
70
  items: { type: 'string' },
65
- description: 'Specific store IDs to search (optional)'
66
- }
71
+ description: 'Specific store IDs to search (optional)',
72
+ },
67
73
  },
68
- required: ['query']
69
- }
74
+ required: ['query'],
75
+ },
70
76
  },
71
77
  // Native get_full_context tool (frequently used after search)
72
78
  {
73
79
  name: 'get_full_context',
74
- description: 'Get complete code and context for a specific search result by ID. Use this after search to get full implementation details.',
80
+ description:
81
+ 'Get complete code and context for a specific search result by ID. Use this after search to get full implementation details.',
75
82
  inputSchema: {
76
83
  type: 'object',
77
84
  properties: {
78
85
  resultId: {
79
86
  type: 'string',
80
- description: 'Result ID from previous search'
81
- }
87
+ description: 'Result ID from previous search',
88
+ },
82
89
  },
83
- required: ['resultId']
84
- }
90
+ required: ['resultId'],
91
+ },
85
92
  },
86
93
  // Meta-tool for store and job management (consolidates 8 tools into 1)
87
94
  {
88
95
  name: 'execute',
89
- description: 'Execute store/job management commands. Commands: stores, store:info, store:create, store:index, store:delete, jobs, job:status, job:cancel, help, commands',
96
+ description:
97
+ 'Execute store/job management commands. Commands: stores, store:info, store:create, store:index, store:delete, jobs, job:status, job:cancel, help, commands',
90
98
  inputSchema: {
91
99
  type: 'object',
92
100
  properties: {
93
101
  command: {
94
102
  type: 'string',
95
- description: 'Command to execute (e.g., "stores", "store:create", "jobs", "help")'
103
+ description: 'Command to execute (e.g., "stores", "store:create", "jobs", "help")',
96
104
  },
97
105
  args: {
98
106
  type: 'object',
99
- description: 'Command arguments (e.g., {store: "mystore"} for store:info)'
100
- }
107
+ description: 'Command arguments (e.g., {store: "mystore"} for store:info)',
108
+ },
101
109
  },
102
- required: ['command']
103
- }
104
- }
105
- ]
110
+ required: ['command'],
111
+ },
112
+ },
113
+ ],
106
114
  });
107
115
  });
108
116
 
@@ -114,11 +122,7 @@ export function createMCPServer(options: MCPServerOptions): Server {
114
122
  logger.info({ tool: name, args: JSON.stringify(args) }, 'Tool invoked');
115
123
 
116
124
  // Create services once (needed by all handlers)
117
- const services = await createServices(
118
- options.config,
119
- options.dataDir,
120
- options.projectRoot
121
- );
125
+ const services = await createServices(options.config, options.dataDir, options.projectRoot);
122
126
  const context = { services, options };
123
127
 
124
128
  try {
@@ -130,7 +134,7 @@ export function createMCPServer(options: MCPServerOptions): Server {
130
134
  result = await handleExecute(validated, context);
131
135
  } else {
132
136
  // Find handler in registry for native tools (search, get_full_context)
133
- const tool = tools.find(t => t.name === name);
137
+ const tool = tools.find((t) => t.name === name);
134
138
  if (tool === undefined) {
135
139
  throw new Error(`Unknown tool: ${name}`);
136
140
  }
@@ -148,11 +152,14 @@ export function createMCPServer(options: MCPServerOptions): Server {
148
152
  return result;
149
153
  } catch (error) {
150
154
  const durationMs = Date.now() - startTime;
151
- logger.error({
152
- tool: name,
153
- durationMs,
154
- error: error instanceof Error ? error.message : String(error),
155
- }, 'Tool execution failed');
155
+ logger.error(
156
+ {
157
+ tool: name,
158
+ durationMs,
159
+ error: error instanceof Error ? error.message : String(error),
160
+ },
161
+ 'Tool execution failed'
162
+ );
156
163
  throw error;
157
164
  }
158
165
  });
@@ -161,10 +168,13 @@ export function createMCPServer(options: MCPServerOptions): Server {
161
168
  }
162
169
 
163
170
  export async function runMCPServer(options: MCPServerOptions): Promise<void> {
164
- logger.info({
165
- dataDir: options.dataDir,
166
- projectRoot: options.projectRoot,
167
- }, 'MCP server starting');
171
+ logger.info(
172
+ {
173
+ dataDir: options.dataDir,
174
+ projectRoot: options.projectRoot,
175
+ },
176
+ 'MCP server starting'
177
+ );
168
178
 
169
179
  const server = createMCPServer(options);
170
180
  const transport = new StdioServerTransport();
@@ -182,9 +192,12 @@ if (isMCPServerEntry) {
182
192
  runMCPServer({
183
193
  dataDir: process.env['DATA_DIR'],
184
194
  config: process.env['CONFIG_PATH'],
185
- projectRoot: process.env['PROJECT_ROOT'] ?? process.env['PWD']
195
+ projectRoot: process.env['PROJECT_ROOT'] ?? process.env['PWD'],
186
196
  }).catch((error: unknown) => {
187
- logger.error({ error: error instanceof Error ? error.message : String(error) }, 'Failed to start MCP server');
197
+ logger.error(
198
+ { error: error instanceof Error ? error.message : String(error) },
199
+ 'Failed to start MCP server'
200
+ );
188
201
  process.exit(1);
189
202
  });
190
203
  }