bluera-knowledge 0.9.32 → 0.9.36

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 (198) 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 +70 -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 +97 -71
  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 +28 -30
  135. package/src/workers/background-worker.test.ts +54 -40
  136. package/src/workers/background-worker.ts +76 -60
  137. package/src/workers/pid-file.test.ts +167 -0
  138. package/src/workers/pid-file.ts +82 -0
  139. package/src/workers/spawn-worker.test.ts +22 -10
  140. package/src/workers/spawn-worker.ts +6 -6
  141. package/tests/analysis/ast-parser.test.ts +3 -3
  142. package/tests/analysis/code-graph.test.ts +5 -5
  143. package/tests/fixtures/code-snippets/api/error-handling.ts +4 -15
  144. package/tests/fixtures/code-snippets/api/rest-controller.ts +3 -9
  145. package/tests/fixtures/code-snippets/auth/jwt-auth.ts +5 -21
  146. package/tests/fixtures/code-snippets/auth/oauth-flow.ts +4 -4
  147. package/tests/fixtures/code-snippets/database/repository-pattern.ts +11 -3
  148. package/tests/fixtures/corpus/oss-repos/hono/src/adapter/aws-lambda/handler.ts +2 -2
  149. package/tests/fixtures/corpus/oss-repos/hono/src/adapter/cloudflare-pages/handler.ts +1 -1
  150. package/tests/fixtures/corpus/oss-repos/hono/src/adapter/cloudflare-workers/serve-static.ts +2 -2
  151. package/tests/fixtures/corpus/oss-repos/hono/src/client/client.ts +2 -2
  152. package/tests/fixtures/corpus/oss-repos/hono/src/client/types.ts +22 -20
  153. package/tests/fixtures/corpus/oss-repos/hono/src/context.ts +13 -10
  154. package/tests/fixtures/corpus/oss-repos/hono/src/helper/accepts/accepts.ts +10 -7
  155. package/tests/fixtures/corpus/oss-repos/hono/src/helper/adapter/index.ts +2 -2
  156. package/tests/fixtures/corpus/oss-repos/hono/src/helper/css/index.ts +1 -1
  157. package/tests/fixtures/corpus/oss-repos/hono/src/helper/factory/index.ts +16 -16
  158. package/tests/fixtures/corpus/oss-repos/hono/src/helper/ssg/ssg.ts +2 -2
  159. package/tests/fixtures/corpus/oss-repos/hono/src/hono-base.ts +3 -3
  160. package/tests/fixtures/corpus/oss-repos/hono/src/hono.ts +1 -1
  161. package/tests/fixtures/corpus/oss-repos/hono/src/jsx/dom/css.ts +2 -2
  162. package/tests/fixtures/corpus/oss-repos/hono/src/jsx/dom/intrinsic-element/components.ts +1 -1
  163. package/tests/fixtures/corpus/oss-repos/hono/src/jsx/dom/render.ts +7 -7
  164. package/tests/fixtures/corpus/oss-repos/hono/src/jsx/hooks/index.ts +3 -3
  165. package/tests/fixtures/corpus/oss-repos/hono/src/jsx/intrinsic-element/components.ts +1 -1
  166. package/tests/fixtures/corpus/oss-repos/hono/src/jsx/utils.ts +6 -6
  167. package/tests/fixtures/corpus/oss-repos/hono/src/middleware/jsx-renderer/index.ts +3 -3
  168. package/tests/fixtures/corpus/oss-repos/hono/src/middleware/serve-static/index.ts +1 -1
  169. package/tests/fixtures/corpus/oss-repos/hono/src/preset/quick.ts +1 -1
  170. package/tests/fixtures/corpus/oss-repos/hono/src/preset/tiny.ts +1 -1
  171. package/tests/fixtures/corpus/oss-repos/hono/src/router/pattern-router/router.ts +2 -2
  172. package/tests/fixtures/corpus/oss-repos/hono/src/router/reg-exp-router/node.ts +4 -4
  173. package/tests/fixtures/corpus/oss-repos/hono/src/router/reg-exp-router/router.ts +1 -1
  174. package/tests/fixtures/corpus/oss-repos/hono/src/router/trie-router/node.ts +1 -1
  175. package/tests/fixtures/corpus/oss-repos/hono/src/types.ts +166 -169
  176. package/tests/fixtures/corpus/oss-repos/hono/src/utils/body.ts +8 -8
  177. package/tests/fixtures/corpus/oss-repos/hono/src/utils/color.ts +3 -3
  178. package/tests/fixtures/corpus/oss-repos/hono/src/utils/cookie.ts +2 -2
  179. package/tests/fixtures/corpus/oss-repos/hono/src/utils/encode.ts +2 -2
  180. package/tests/fixtures/corpus/oss-repos/hono/src/utils/types.ts +30 -33
  181. package/tests/fixtures/corpus/oss-repos/hono/src/validator/validator.ts +2 -2
  182. package/tests/fixtures/test-server.ts +3 -2
  183. package/tests/helpers/performance-metrics.ts +8 -25
  184. package/tests/helpers/search-relevance.ts +14 -69
  185. package/tests/integration/cli-consistency.test.ts +6 -5
  186. package/tests/integration/python-bridge.test.ts +13 -3
  187. package/tests/mcp/server.test.ts +1 -1
  188. package/tests/services/code-unit.service.test.ts +48 -0
  189. package/tests/services/job.service.test.ts +124 -0
  190. package/tests/services/search.progressive-context.test.ts +2 -2
  191. package/.claude-plugin/plugin.json +0 -13
  192. package/dist/chunk-6PBP5DVD.js.map +0 -1
  193. package/dist/chunk-L2YVNC63.js.map +0 -1
  194. package/dist/chunk-RST4XGRL.js.map +0 -1
  195. package/dist/chunk-WT2DAEO7.js.map +0 -1
  196. package/dist/watch.service-YAIKKDCF.js +0 -7
  197. package/skills/atomic-commits/SKILL.md +0 -77
  198. /package/dist/{watch.service-YAIKKDCF.js.map → watch.service-BJV3TI3F.js.map} +0 -0
@@ -4,21 +4,27 @@ import {
4
4
  createServices,
5
5
  createStoreId,
6
6
  summarizePayload
7
- } from "./chunk-6PBP5DVD.js";
7
+ } from "./chunk-WFNPNAAP.js";
8
8
 
9
9
  // src/mcp/server.ts
10
10
  import { Server } from "@modelcontextprotocol/sdk/server/index.js";
11
11
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
12
- import {
13
- CallToolRequestSchema,
14
- ListToolsRequestSchema
15
- } from "@modelcontextprotocol/sdk/types.js";
12
+ import { CallToolRequestSchema, ListToolsRequestSchema } from "@modelcontextprotocol/sdk/types.js";
13
+
14
+ // src/mcp/commands/job.commands.ts
15
+ import { z as z2 } from "zod";
16
16
 
17
17
  // src/mcp/schemas/index.ts
18
18
  import { z } from "zod";
19
19
  var SearchArgsSchema = z.object({
20
20
  query: z.string().min(1, "Query must be a non-empty string"),
21
- intent: z.enum(["find-pattern", "find-implementation", "find-usage", "find-definition", "find-documentation"]).optional(),
21
+ intent: z.enum([
22
+ "find-pattern",
23
+ "find-implementation",
24
+ "find-usage",
25
+ "find-definition",
26
+ "find-documentation"
27
+ ]).optional(),
22
28
  detail: z.enum(["minimal", "contextual", "full"]).default("minimal"),
23
29
  limit: z.number().int().positive().default(10),
24
30
  stores: z.array(z.string()).optional()
@@ -60,288 +66,106 @@ var ExecuteArgsSchema = z.object({
60
66
  args: z.record(z.string(), z.unknown()).optional()
61
67
  });
62
68
 
63
- // src/mcp/cache.ts
64
- var LRUCache = class {
65
- cache = /* @__PURE__ */ new Map();
66
- maxSize;
67
- /**
68
- * Create a new LRU cache
69
- *
70
- * @param maxSize - Maximum number of items to store (default: 1000)
71
- */
72
- constructor(maxSize = 1e3) {
73
- this.maxSize = maxSize;
69
+ // src/mcp/handlers/job.handler.ts
70
+ var handleCheckJobStatus = (args, context) => {
71
+ const validated = CheckJobStatusArgsSchema.parse(args);
72
+ const { options } = context;
73
+ const jobService = new JobService(options.dataDir);
74
+ const job = jobService.getJob(validated.jobId);
75
+ if (!job) {
76
+ throw new Error(`Job not found: ${validated.jobId}`);
74
77
  }
75
- /**
76
- * Store a value in the cache
77
- *
78
- * If the key already exists, it will be moved to the end (most recent).
79
- * If the cache is at capacity, the oldest item will be evicted.
80
- *
81
- * @param key - The cache key
82
- * @param value - The value to store
83
- */
84
- set(key, value) {
85
- if (this.cache.has(key)) {
86
- this.cache.delete(key);
87
- }
88
- this.cache.set(key, value);
89
- if (this.cache.size > this.maxSize) {
90
- const firstKey = this.cache.keys().next().value;
91
- if (firstKey !== void 0) {
92
- this.cache.delete(firstKey);
78
+ return Promise.resolve({
79
+ content: [
80
+ {
81
+ type: "text",
82
+ text: JSON.stringify(job, null, 2)
93
83
  }
94
- }
95
- }
96
- /**
97
- * Retrieve a value from the cache
98
- *
99
- * If the key exists, it will be moved to the end (most recent).
100
- *
101
- * @param key - The cache key
102
- * @returns The cached value, or undefined if not found
103
- */
104
- get(key) {
105
- const value = this.cache.get(key);
106
- if (value !== void 0) {
107
- this.cache.delete(key);
108
- this.cache.set(key, value);
109
- }
110
- return value;
111
- }
112
- /**
113
- * Check if a key exists in the cache
114
- *
115
- * @param key - The cache key
116
- * @returns True if the key exists
117
- */
118
- has(key) {
119
- return this.cache.has(key);
120
- }
121
- /**
122
- * Remove a specific key from the cache
123
- *
124
- * @param key - The cache key
125
- * @returns True if the key was removed, false if it didn't exist
126
- */
127
- delete(key) {
128
- return this.cache.delete(key);
129
- }
130
- /**
131
- * Clear all entries from the cache
132
- */
133
- clear() {
134
- this.cache.clear();
135
- }
136
- /**
137
- * Get the current number of items in the cache
138
- */
139
- get size() {
140
- return this.cache.size;
141
- }
84
+ ]
85
+ });
142
86
  };
143
-
144
- // src/services/token.service.ts
145
- var CHARS_PER_TOKEN = 3.5;
146
- function estimateTokens(text) {
147
- if (!text) return 0;
148
- return Math.ceil(text.length / CHARS_PER_TOKEN);
149
- }
150
- function formatTokenCount(tokens) {
151
- if (tokens >= 1e3) {
152
- return `~${(tokens / 1e3).toFixed(1)}k`;
153
- }
154
- return `~${String(tokens)}`;
155
- }
156
-
157
- // src/mcp/handlers/search.handler.ts
158
- var logger = createLogger("mcp-search");
159
- var resultCache = new LRUCache(1e3);
160
- var handleSearch = async (args, context) => {
161
- const validated = SearchArgsSchema.parse(args);
162
- logger.info({
163
- query: validated.query,
164
- stores: validated.stores,
165
- detail: validated.detail,
166
- limit: validated.limit,
167
- intent: validated.intent
168
- }, "Search started");
169
- const { services } = context;
170
- const storeIds = validated.stores !== void 0 ? await Promise.all(validated.stores.map(async (s) => {
171
- const store = await services.store.getByIdOrName(s);
172
- if (!store) {
173
- throw new Error(`Store not found: ${s}`);
174
- }
175
- return store.id;
176
- })) : (await services.store.list()).map((s) => s.id);
177
- try {
178
- for (const storeId of storeIds) {
179
- await services.lance.initialize(storeId);
180
- }
181
- } catch (error) {
182
- throw new Error(
183
- `Failed to initialize vector stores: ${error instanceof Error ? error.message : String(error)}`
184
- );
185
- }
186
- const searchQuery = {
187
- query: validated.query,
188
- stores: storeIds,
189
- mode: "hybrid",
190
- limit: validated.limit,
191
- detail: validated.detail
192
- };
193
- const results = await services.search.search(searchQuery);
194
- for (const result of results.results) {
195
- resultCache.set(result.id, result);
87
+ var handleListJobs = (args, context) => {
88
+ const validated = ListJobsArgsSchema.parse(args);
89
+ const { options } = context;
90
+ const jobService = new JobService(options.dataDir);
91
+ let jobs;
92
+ if (validated.activeOnly === true) {
93
+ jobs = jobService.listActiveJobs();
94
+ } else if (validated.status !== void 0) {
95
+ jobs = jobService.listJobs(validated.status);
96
+ } else {
97
+ jobs = jobService.listJobs();
196
98
  }
197
- const enhancedResults = await Promise.all(results.results.map(async (r) => {
198
- const storeId = r.metadata.storeId;
199
- const store = await services.store.getByIdOrName(storeId);
200
- return {
201
- id: r.id,
202
- score: r.score,
203
- summary: {
204
- ...r.summary,
205
- storeName: store?.name,
206
- repoRoot: store !== void 0 && store.type === "repo" ? store.path : void 0
207
- },
208
- context: r.context,
209
- full: r.full
210
- };
211
- }));
212
- const responseJson = JSON.stringify({
213
- results: enhancedResults,
214
- totalResults: results.totalResults,
215
- mode: results.mode,
216
- timeMs: results.timeMs
217
- }, null, 2);
218
- const responseTokens = estimateTokens(responseJson);
219
- const header = `Search: "${validated.query}" | Results: ${String(results.totalResults)} | ${formatTokenCount(responseTokens)} tokens | ${String(results.timeMs)}ms
220
-
221
- `;
222
- logger.info({
223
- query: validated.query,
224
- totalResults: results.totalResults,
225
- responseTokens,
226
- timeMs: results.timeMs,
227
- ...summarizePayload(responseJson, "mcp-response", validated.query)
228
- }, "Search complete - context sent to Claude Code");
229
- return {
99
+ return Promise.resolve({
230
100
  content: [
231
101
  {
232
102
  type: "text",
233
- text: header + responseJson
103
+ text: JSON.stringify({ jobs }, null, 2)
234
104
  }
235
105
  ]
236
- };
106
+ });
237
107
  };
238
- var handleGetFullContext = async (args, context) => {
239
- const validated = GetFullContextArgsSchema.parse(args);
240
- logger.info({ resultId: validated.resultId }, "Get full context requested");
241
- const resultId = validated.resultId;
242
- const cachedResult = resultCache.get(resultId);
243
- if (!cachedResult) {
244
- throw new Error(
245
- `Result not found in cache: ${resultId}. Run a search first to cache results.`
246
- );
247
- }
248
- if (cachedResult.full) {
249
- const responseJson2 = JSON.stringify({
250
- id: cachedResult.id,
251
- score: cachedResult.score,
252
- summary: cachedResult.summary,
253
- context: cachedResult.context,
254
- full: cachedResult.full
255
- }, null, 2);
256
- logger.info({
257
- resultId,
258
- cached: true,
259
- hasFullContext: true,
260
- ...summarizePayload(responseJson2, "mcp-full-context", resultId)
261
- }, "Full context retrieved from cache");
262
- return {
263
- content: [
264
- {
265
- type: "text",
266
- text: responseJson2
267
- }
268
- ]
269
- };
270
- }
271
- const { services } = context;
272
- const store = await services.store.getByIdOrName(cachedResult.metadata.storeId);
273
- if (!store) {
274
- throw new Error(`Store not found: ${cachedResult.metadata.storeId}`);
275
- }
276
- await services.lance.initialize(store.id);
277
- const searchQuery = {
278
- query: cachedResult.content.substring(0, 100),
279
- // Use snippet of content as query
280
- stores: [store.id],
281
- mode: "hybrid",
282
- limit: 1,
283
- detail: "full"
284
- };
285
- const results = await services.search.search(searchQuery);
286
- const fullResult = results.results.find((r) => r.id === resultId);
287
- if (!fullResult) {
288
- return {
289
- content: [
290
- {
291
- type: "text",
292
- text: JSON.stringify({
293
- id: cachedResult.id,
294
- score: cachedResult.score,
295
- summary: cachedResult.summary,
296
- context: cachedResult.context,
297
- warning: "Could not retrieve full context, returning cached minimal result"
298
- }, null, 2)
299
- }
300
- ]
301
- };
108
+ var handleCancelJob = (args, context) => {
109
+ const validated = CancelJobArgsSchema.parse(args);
110
+ const { options } = context;
111
+ const jobService = new JobService(options.dataDir);
112
+ const result = jobService.cancelJob(validated.jobId);
113
+ if (!result.success) {
114
+ throw new Error(result.error.message);
302
115
  }
303
- resultCache.set(resultId, fullResult);
304
- const responseJson = JSON.stringify({
305
- id: fullResult.id,
306
- score: fullResult.score,
307
- summary: fullResult.summary,
308
- context: fullResult.context,
309
- full: fullResult.full
310
- }, null, 2);
311
- logger.info({
312
- resultId,
313
- cached: false,
314
- hasFullContext: true,
315
- ...summarizePayload(responseJson, "mcp-full-context", resultId)
316
- }, "Full context retrieved via re-query");
317
- return {
116
+ const job = jobService.getJob(validated.jobId);
117
+ return Promise.resolve({
318
118
  content: [
319
119
  {
320
120
  type: "text",
321
- text: responseJson
121
+ text: JSON.stringify(
122
+ {
123
+ success: true,
124
+ job,
125
+ message: "Job cancelled successfully"
126
+ },
127
+ null,
128
+ 2
129
+ )
322
130
  }
323
131
  ]
324
- };
132
+ });
325
133
  };
326
134
 
327
- // src/mcp/handlers/index.ts
328
- var tools = [
135
+ // src/mcp/commands/job.commands.ts
136
+ var jobCommands = [
329
137
  {
330
- name: "search",
331
- description: "Search all indexed knowledge stores with pattern detection and AI-optimized results. Returns structured code units with progressive context layers.",
332
- schema: SearchArgsSchema,
333
- handler: handleSearch
138
+ name: "jobs",
139
+ description: "List all background jobs",
140
+ argsSchema: z2.object({
141
+ activeOnly: z2.boolean().optional().describe("Only show active jobs"),
142
+ status: z2.enum(["pending", "running", "completed", "failed", "cancelled"]).optional().describe("Filter by job status")
143
+ }),
144
+ handler: (args, context) => handleListJobs(args, context)
334
145
  },
335
146
  {
336
- name: "get_full_context",
337
- description: "Get complete code and context for a specific search result by ID. Use this after search to get full implementation details.",
338
- schema: GetFullContextArgsSchema,
339
- handler: handleGetFullContext
147
+ name: "job:status",
148
+ description: "Check the status of a specific background job",
149
+ argsSchema: z2.object({
150
+ jobId: z2.string().min(1).describe("Job ID to check")
151
+ }),
152
+ handler: (args, context) => handleCheckJobStatus(args, context)
153
+ },
154
+ {
155
+ name: "job:cancel",
156
+ description: "Cancel a running or pending background job",
157
+ argsSchema: z2.object({
158
+ jobId: z2.string().min(1).describe("Job ID to cancel")
159
+ }),
160
+ handler: (args, context) => handleCancelJob(args, context)
340
161
  }
341
162
  ];
342
163
 
164
+ // src/mcp/commands/meta.commands.ts
165
+ import { z as z4 } from "zod";
166
+
343
167
  // src/mcp/commands/registry.ts
344
- import { z as z2 } from "zod";
168
+ import { z as z3 } from "zod";
345
169
  var CommandRegistry = class {
346
170
  commands = /* @__PURE__ */ new Map();
347
171
  /**
@@ -411,15 +235,11 @@ function generateHelp(commandName) {
411
235
  if (command === void 0) {
412
236
  throw new Error(`Unknown command: ${commandName}`);
413
237
  }
414
- const lines2 = [
415
- `Command: ${command.name}`,
416
- `Description: ${command.description}`,
417
- ""
418
- ];
238
+ const lines2 = [`Command: ${command.name}`, `Description: ${command.description}`, ""];
419
239
  if (command.argsSchema !== void 0) {
420
240
  lines2.push("Arguments:");
421
241
  const schema = command.argsSchema;
422
- if (schema instanceof z2.ZodObject) {
242
+ if (schema instanceof z3.ZodObject) {
423
243
  const shape = schema.shape;
424
244
  for (const [key, fieldSchema] of Object.entries(shape)) {
425
245
  const isOptional = fieldSchema.safeParse(void 0).success;
@@ -445,8 +265,50 @@ function generateHelp(commandName) {
445
265
  return lines.join("\n");
446
266
  }
447
267
 
448
- // src/mcp/commands/store.commands.ts
449
- import { z as z3 } from "zod";
268
+ // src/mcp/commands/meta.commands.ts
269
+ var metaCommands = [
270
+ {
271
+ name: "commands",
272
+ description: "List all available commands",
273
+ handler: () => {
274
+ const commands = commandRegistry.all();
275
+ const commandList = commands.map((cmd) => ({
276
+ name: cmd.name,
277
+ description: cmd.description
278
+ }));
279
+ return Promise.resolve({
280
+ content: [
281
+ {
282
+ type: "text",
283
+ text: JSON.stringify({ commands: commandList }, null, 2)
284
+ }
285
+ ]
286
+ });
287
+ }
288
+ },
289
+ {
290
+ name: "help",
291
+ description: "Show help for a specific command or list all commands",
292
+ argsSchema: z4.object({
293
+ command: z4.string().optional().describe("Command name to get help for")
294
+ }),
295
+ handler: (args) => {
296
+ const commandName = args["command"];
297
+ const helpText = generateHelp(commandName);
298
+ return Promise.resolve({
299
+ content: [
300
+ {
301
+ type: "text",
302
+ text: helpText
303
+ }
304
+ ]
305
+ });
306
+ }
307
+ }
308
+ ];
309
+
310
+ // src/mcp/commands/store.commands.ts
311
+ import { z as z5 } from "zod";
450
312
 
451
313
  // src/mcp/handlers/store.handler.ts
452
314
  import { rm } from "fs/promises";
@@ -454,8 +316,8 @@ import { join } from "path";
454
316
 
455
317
  // src/workers/spawn-worker.ts
456
318
  import { spawn } from "child_process";
457
- import { fileURLToPath } from "url";
458
319
  import path from "path";
320
+ import { fileURLToPath } from "url";
459
321
  function spawnBackgroundWorker(jobId, dataDir) {
460
322
  const __dirname2 = path.dirname(fileURLToPath(import.meta.url));
461
323
  const isProduction = __dirname2.includes("/dist/");
@@ -495,17 +357,21 @@ var handleListStores = async (args, context) => {
495
357
  content: [
496
358
  {
497
359
  type: "text",
498
- text: JSON.stringify({
499
- stores: filtered.map((s) => ({
500
- id: s.id,
501
- name: s.name,
502
- type: s.type,
503
- path: "path" in s ? s.path : void 0,
504
- url: "url" in s && s.url !== void 0 ? s.url : void 0,
505
- description: s.description,
506
- createdAt: s.createdAt.toISOString()
507
- }))
508
- }, null, 2)
360
+ text: JSON.stringify(
361
+ {
362
+ stores: filtered.map((s) => ({
363
+ id: s.id,
364
+ name: s.name,
365
+ type: s.type,
366
+ path: "path" in s ? s.path : void 0,
367
+ url: "url" in s && s.url !== void 0 ? s.url : void 0,
368
+ description: s.description,
369
+ createdAt: s.createdAt.toISOString()
370
+ }))
371
+ },
372
+ null,
373
+ 2
374
+ )
509
375
  }
510
376
  ]
511
377
  };
@@ -521,18 +387,22 @@ var handleGetStoreInfo = async (args, context) => {
521
387
  content: [
522
388
  {
523
389
  type: "text",
524
- text: JSON.stringify({
525
- id: store.id,
526
- name: store.name,
527
- type: store.type,
528
- path: "path" in store ? store.path : void 0,
529
- url: "url" in store && store.url !== void 0 ? store.url : void 0,
530
- branch: "branch" in store ? store.branch : void 0,
531
- description: store.description,
532
- status: store.status,
533
- createdAt: store.createdAt.toISOString(),
534
- updatedAt: store.updatedAt.toISOString()
535
- }, null, 2)
390
+ text: JSON.stringify(
391
+ {
392
+ id: store.id,
393
+ name: store.name,
394
+ type: store.type,
395
+ path: "path" in store ? store.path : void 0,
396
+ url: "url" in store && store.url !== void 0 ? store.url : void 0,
397
+ branch: "branch" in store ? store.branch : void 0,
398
+ description: store.description,
399
+ status: store.status,
400
+ createdAt: store.createdAt.toISOString(),
401
+ updatedAt: store.updatedAt.toISOString()
402
+ },
403
+ null,
404
+ 2
405
+ )
536
406
  }
537
407
  ]
538
408
  };
@@ -572,20 +442,24 @@ var handleCreateStore = async (args, context) => {
572
442
  content: [
573
443
  {
574
444
  type: "text",
575
- text: JSON.stringify({
576
- store: {
577
- id: result.data.id,
578
- name: result.data.name,
579
- type: result.data.type,
580
- path: "path" in result.data ? result.data.path : void 0
581
- },
582
- job: {
583
- id: job.id,
584
- status: job.status,
585
- message: job.message
445
+ text: JSON.stringify(
446
+ {
447
+ store: {
448
+ id: result.data.id,
449
+ name: result.data.name,
450
+ type: result.data.type,
451
+ path: "path" in result.data ? result.data.path : void 0
452
+ },
453
+ job: {
454
+ id: job.id,
455
+ status: job.status,
456
+ message: job.message
457
+ },
458
+ message: `Store created. Indexing started in background (Job ID: ${job.id})`
586
459
  },
587
- message: `Store created. Indexing started in background (Job ID: ${job.id})`
588
- }, null, 2)
460
+ null,
461
+ 2
462
+ )
589
463
  }
590
464
  ]
591
465
  };
@@ -615,18 +489,22 @@ var handleIndexStore = async (args, context) => {
615
489
  content: [
616
490
  {
617
491
  type: "text",
618
- text: JSON.stringify({
619
- store: {
620
- id: store.id,
621
- name: store.name
622
- },
623
- job: {
624
- id: job.id,
625
- status: job.status,
626
- message: job.message
492
+ text: JSON.stringify(
493
+ {
494
+ store: {
495
+ id: store.id,
496
+ name: store.name
497
+ },
498
+ job: {
499
+ id: job.id,
500
+ status: job.status,
501
+ message: job.message
502
+ },
503
+ message: `Indexing started in background (Job ID: ${job.id})`
627
504
  },
628
- message: `Indexing started in background (Job ID: ${job.id})`
629
- }, null, 2)
505
+ null,
506
+ 2
507
+ )
630
508
  }
631
509
  ]
632
510
  };
@@ -654,15 +532,19 @@ var handleDeleteStore = async (args, context) => {
654
532
  content: [
655
533
  {
656
534
  type: "text",
657
- text: JSON.stringify({
658
- deleted: true,
659
- store: {
660
- id: store.id,
661
- name: store.name,
662
- type: store.type
535
+ text: JSON.stringify(
536
+ {
537
+ deleted: true,
538
+ store: {
539
+ id: store.id,
540
+ name: store.name,
541
+ type: store.type
542
+ },
543
+ message: `Successfully deleted store: ${store.name}`
663
544
  },
664
- message: `Successfully deleted store: ${store.name}`
665
- }, null, 2)
545
+ null,
546
+ 2
547
+ )
666
548
  }
667
549
  ]
668
550
  };
@@ -673,198 +555,371 @@ var storeCommands = [
673
555
  {
674
556
  name: "stores",
675
557
  description: "List all indexed knowledge stores",
676
- argsSchema: z3.object({
677
- type: z3.enum(["file", "repo", "web"]).optional().describe("Filter by store type")
558
+ argsSchema: z5.object({
559
+ type: z5.enum(["file", "repo", "web"]).optional().describe("Filter by store type")
678
560
  }),
679
561
  handler: (args, context) => handleListStores(args, context)
680
562
  },
681
563
  {
682
564
  name: "store:info",
683
565
  description: "Get detailed information about a specific store",
684
- argsSchema: z3.object({
685
- store: z3.string().min(1).describe("Store name or ID")
566
+ argsSchema: z5.object({
567
+ store: z5.string().min(1).describe("Store name or ID")
686
568
  }),
687
569
  handler: (args, context) => handleGetStoreInfo(args, context)
688
570
  },
689
571
  {
690
572
  name: "store:create",
691
573
  description: "Create a new knowledge store from git URL or local path",
692
- argsSchema: z3.object({
693
- name: z3.string().min(1).describe("Store name"),
694
- type: z3.enum(["file", "repo"]).describe("Store type"),
695
- source: z3.string().min(1).describe("Git URL or local path"),
696
- branch: z3.string().optional().describe("Git branch (for repo type)"),
697
- description: z3.string().optional().describe("Store description")
574
+ argsSchema: z5.object({
575
+ name: z5.string().min(1).describe("Store name"),
576
+ type: z5.enum(["file", "repo"]).describe("Store type"),
577
+ source: z5.string().min(1).describe("Git URL or local path"),
578
+ branch: z5.string().optional().describe("Git branch (for repo type)"),
579
+ description: z5.string().optional().describe("Store description")
698
580
  }),
699
581
  handler: (args, context) => handleCreateStore(args, context)
700
582
  },
701
583
  {
702
584
  name: "store:index",
703
585
  description: "Re-index a knowledge store to update search data",
704
- argsSchema: z3.object({
705
- store: z3.string().min(1).describe("Store name or ID")
586
+ argsSchema: z5.object({
587
+ store: z5.string().min(1).describe("Store name or ID")
706
588
  }),
707
589
  handler: (args, context) => handleIndexStore(args, context)
708
590
  },
709
591
  {
710
592
  name: "store:delete",
711
593
  description: "Delete a knowledge store and all associated data",
712
- argsSchema: z3.object({
713
- store: z3.string().min(1).describe("Store name or ID")
594
+ argsSchema: z5.object({
595
+ store: z5.string().min(1).describe("Store name or ID")
714
596
  }),
715
597
  handler: (args, context) => handleDeleteStore(args, context)
716
598
  }
717
599
  ];
718
600
 
719
- // src/mcp/commands/job.commands.ts
720
- import { z as z4 } from "zod";
601
+ // src/mcp/commands/index.ts
602
+ commandRegistry.registerAll(storeCommands);
603
+ commandRegistry.registerAll(jobCommands);
604
+ commandRegistry.registerAll(metaCommands);
721
605
 
722
- // src/mcp/handlers/job.handler.ts
723
- var handleCheckJobStatus = (args, context) => {
724
- const validated = CheckJobStatusArgsSchema.parse(args);
725
- const { options } = context;
726
- const jobService = new JobService(options.dataDir);
727
- const job = jobService.getJob(validated.jobId);
728
- if (!job) {
729
- throw new Error(`Job not found: ${validated.jobId}`);
606
+ // src/mcp/handlers/execute.handler.ts
607
+ var handleExecute = async (args, context) => {
608
+ const validated = ExecuteArgsSchema.parse(args);
609
+ const commandArgs = validated.args ?? {};
610
+ return executeCommand(validated.command, commandArgs, context);
611
+ };
612
+
613
+ // src/services/token.service.ts
614
+ var CHARS_PER_TOKEN = 3.5;
615
+ function estimateTokens(text) {
616
+ if (!text) return 0;
617
+ return Math.ceil(text.length / CHARS_PER_TOKEN);
618
+ }
619
+ function formatTokenCount(tokens) {
620
+ if (tokens >= 1e3) {
621
+ return `~${(tokens / 1e3).toFixed(1)}k`;
730
622
  }
731
- return Promise.resolve({
732
- content: [
733
- {
734
- type: "text",
735
- text: JSON.stringify(job, null, 2)
623
+ return `~${String(tokens)}`;
624
+ }
625
+
626
+ // src/mcp/cache.ts
627
+ var LRUCache = class {
628
+ cache = /* @__PURE__ */ new Map();
629
+ maxSize;
630
+ /**
631
+ * Create a new LRU cache
632
+ *
633
+ * @param maxSize - Maximum number of items to store (default: 1000)
634
+ */
635
+ constructor(maxSize = 1e3) {
636
+ this.maxSize = maxSize;
637
+ }
638
+ /**
639
+ * Store a value in the cache
640
+ *
641
+ * If the key already exists, it will be moved to the end (most recent).
642
+ * If the cache is at capacity, the oldest item will be evicted.
643
+ *
644
+ * @param key - The cache key
645
+ * @param value - The value to store
646
+ */
647
+ set(key, value) {
648
+ if (this.cache.has(key)) {
649
+ this.cache.delete(key);
650
+ }
651
+ this.cache.set(key, value);
652
+ if (this.cache.size > this.maxSize) {
653
+ const firstKey = this.cache.keys().next().value;
654
+ if (firstKey !== void 0) {
655
+ this.cache.delete(firstKey);
736
656
  }
737
- ]
738
- });
657
+ }
658
+ }
659
+ /**
660
+ * Retrieve a value from the cache
661
+ *
662
+ * If the key exists, it will be moved to the end (most recent).
663
+ *
664
+ * @param key - The cache key
665
+ * @returns The cached value, or undefined if not found
666
+ */
667
+ get(key) {
668
+ const value = this.cache.get(key);
669
+ if (value !== void 0) {
670
+ this.cache.delete(key);
671
+ this.cache.set(key, value);
672
+ }
673
+ return value;
674
+ }
675
+ /**
676
+ * Check if a key exists in the cache
677
+ *
678
+ * @param key - The cache key
679
+ * @returns True if the key exists
680
+ */
681
+ has(key) {
682
+ return this.cache.has(key);
683
+ }
684
+ /**
685
+ * Remove a specific key from the cache
686
+ *
687
+ * @param key - The cache key
688
+ * @returns True if the key was removed, false if it didn't exist
689
+ */
690
+ delete(key) {
691
+ return this.cache.delete(key);
692
+ }
693
+ /**
694
+ * Clear all entries from the cache
695
+ */
696
+ clear() {
697
+ this.cache.clear();
698
+ }
699
+ /**
700
+ * Get the current number of items in the cache
701
+ */
702
+ get size() {
703
+ return this.cache.size;
704
+ }
739
705
  };
740
- var handleListJobs = (args, context) => {
741
- const validated = ListJobsArgsSchema.parse(args);
742
- const { options } = context;
743
- const jobService = new JobService(options.dataDir);
744
- let jobs;
745
- if (validated.activeOnly === true) {
746
- jobs = jobService.listActiveJobs();
747
- } else if (validated.status !== void 0) {
748
- jobs = jobService.listJobs(validated.status);
749
- } else {
750
- jobs = jobService.listJobs();
706
+
707
+ // src/mcp/handlers/search.handler.ts
708
+ var logger = createLogger("mcp-search");
709
+ var resultCache = new LRUCache(1e3);
710
+ var handleSearch = async (args, context) => {
711
+ const validated = SearchArgsSchema.parse(args);
712
+ logger.info(
713
+ {
714
+ query: validated.query,
715
+ stores: validated.stores,
716
+ detail: validated.detail,
717
+ limit: validated.limit,
718
+ intent: validated.intent
719
+ },
720
+ "Search started"
721
+ );
722
+ const { services } = context;
723
+ const storeIds = validated.stores !== void 0 ? await Promise.all(
724
+ validated.stores.map(async (s) => {
725
+ const store = await services.store.getByIdOrName(s);
726
+ if (!store) {
727
+ throw new Error(`Store not found: ${s}`);
728
+ }
729
+ return store.id;
730
+ })
731
+ ) : (await services.store.list()).map((s) => s.id);
732
+ try {
733
+ for (const storeId of storeIds) {
734
+ await services.lance.initialize(storeId);
735
+ }
736
+ } catch (error) {
737
+ throw new Error(
738
+ `Failed to initialize vector stores: ${error instanceof Error ? error.message : String(error)}`
739
+ );
751
740
  }
752
- return Promise.resolve({
741
+ const searchQuery = {
742
+ query: validated.query,
743
+ stores: storeIds,
744
+ mode: "hybrid",
745
+ limit: validated.limit,
746
+ detail: validated.detail
747
+ };
748
+ const results = await services.search.search(searchQuery);
749
+ for (const result of results.results) {
750
+ resultCache.set(result.id, result);
751
+ }
752
+ const enhancedResults = await Promise.all(
753
+ results.results.map(async (r) => {
754
+ const storeId = r.metadata.storeId;
755
+ const store = await services.store.getByIdOrName(storeId);
756
+ return {
757
+ id: r.id,
758
+ score: r.score,
759
+ summary: {
760
+ ...r.summary,
761
+ storeName: store?.name,
762
+ repoRoot: store?.type === "repo" ? store.path : void 0
763
+ },
764
+ context: r.context,
765
+ full: r.full
766
+ };
767
+ })
768
+ );
769
+ const responseJson = JSON.stringify(
770
+ {
771
+ results: enhancedResults,
772
+ totalResults: results.totalResults,
773
+ mode: results.mode,
774
+ timeMs: results.timeMs
775
+ },
776
+ null,
777
+ 2
778
+ );
779
+ const responseTokens = estimateTokens(responseJson);
780
+ const header = `Search: "${validated.query}" | Results: ${String(results.totalResults)} | ${formatTokenCount(responseTokens)} tokens | ${String(results.timeMs)}ms
781
+
782
+ `;
783
+ logger.info(
784
+ {
785
+ query: validated.query,
786
+ totalResults: results.totalResults,
787
+ responseTokens,
788
+ timeMs: results.timeMs,
789
+ ...summarizePayload(responseJson, "mcp-response", validated.query)
790
+ },
791
+ "Search complete - context sent to Claude Code"
792
+ );
793
+ return {
753
794
  content: [
754
795
  {
755
796
  type: "text",
756
- text: JSON.stringify({ jobs }, null, 2)
797
+ text: header + responseJson
757
798
  }
758
799
  ]
759
- });
800
+ };
760
801
  };
761
- var handleCancelJob = (args, context) => {
762
- const validated = CancelJobArgsSchema.parse(args);
763
- const { options } = context;
764
- const jobService = new JobService(options.dataDir);
765
- const result = jobService.cancelJob(validated.jobId);
766
- if (!result.success) {
767
- throw new Error(result.error.message);
802
+ var handleGetFullContext = async (args, context) => {
803
+ const validated = GetFullContextArgsSchema.parse(args);
804
+ logger.info({ resultId: validated.resultId }, "Get full context requested");
805
+ const resultId = validated.resultId;
806
+ const cachedResult = resultCache.get(resultId);
807
+ if (!cachedResult) {
808
+ throw new Error(`Result not found in cache: ${resultId}. Run a search first to cache results.`);
768
809
  }
769
- const job = jobService.getJob(validated.jobId);
770
- return Promise.resolve({
810
+ if (cachedResult.full) {
811
+ const responseJson2 = JSON.stringify(
812
+ {
813
+ id: cachedResult.id,
814
+ score: cachedResult.score,
815
+ summary: cachedResult.summary,
816
+ context: cachedResult.context,
817
+ full: cachedResult.full
818
+ },
819
+ null,
820
+ 2
821
+ );
822
+ logger.info(
823
+ {
824
+ resultId,
825
+ cached: true,
826
+ hasFullContext: true,
827
+ ...summarizePayload(responseJson2, "mcp-full-context", resultId)
828
+ },
829
+ "Full context retrieved from cache"
830
+ );
831
+ return {
832
+ content: [
833
+ {
834
+ type: "text",
835
+ text: responseJson2
836
+ }
837
+ ]
838
+ };
839
+ }
840
+ const { services } = context;
841
+ const store = await services.store.getByIdOrName(cachedResult.metadata.storeId);
842
+ if (!store) {
843
+ throw new Error(`Store not found: ${cachedResult.metadata.storeId}`);
844
+ }
845
+ await services.lance.initialize(store.id);
846
+ const searchQuery = {
847
+ query: cachedResult.content.substring(0, 100),
848
+ // Use snippet of content as query
849
+ stores: [store.id],
850
+ mode: "hybrid",
851
+ limit: 1,
852
+ detail: "full"
853
+ };
854
+ const results = await services.search.search(searchQuery);
855
+ const fullResult = results.results.find((r) => r.id === resultId);
856
+ if (!fullResult) {
857
+ return {
858
+ content: [
859
+ {
860
+ type: "text",
861
+ text: JSON.stringify(
862
+ {
863
+ id: cachedResult.id,
864
+ score: cachedResult.score,
865
+ summary: cachedResult.summary,
866
+ context: cachedResult.context,
867
+ warning: "Could not retrieve full context, returning cached minimal result"
868
+ },
869
+ null,
870
+ 2
871
+ )
872
+ }
873
+ ]
874
+ };
875
+ }
876
+ resultCache.set(resultId, fullResult);
877
+ const responseJson = JSON.stringify(
878
+ {
879
+ id: fullResult.id,
880
+ score: fullResult.score,
881
+ summary: fullResult.summary,
882
+ context: fullResult.context,
883
+ full: fullResult.full
884
+ },
885
+ null,
886
+ 2
887
+ );
888
+ logger.info(
889
+ {
890
+ resultId,
891
+ cached: false,
892
+ hasFullContext: true,
893
+ ...summarizePayload(responseJson, "mcp-full-context", resultId)
894
+ },
895
+ "Full context retrieved via re-query"
896
+ );
897
+ return {
771
898
  content: [
772
899
  {
773
900
  type: "text",
774
- text: JSON.stringify({
775
- success: true,
776
- job,
777
- message: "Job cancelled successfully"
778
- }, null, 2)
901
+ text: responseJson
779
902
  }
780
903
  ]
781
- });
904
+ };
782
905
  };
783
906
 
784
- // src/mcp/commands/job.commands.ts
785
- var jobCommands = [
786
- {
787
- name: "jobs",
788
- description: "List all background jobs",
789
- argsSchema: z4.object({
790
- activeOnly: z4.boolean().optional().describe("Only show active jobs"),
791
- status: z4.enum(["pending", "running", "completed", "failed", "cancelled"]).optional().describe("Filter by job status")
792
- }),
793
- handler: (args, context) => handleListJobs(args, context)
794
- },
795
- {
796
- name: "job:status",
797
- description: "Check the status of a specific background job",
798
- argsSchema: z4.object({
799
- jobId: z4.string().min(1).describe("Job ID to check")
800
- }),
801
- handler: (args, context) => handleCheckJobStatus(args, context)
802
- },
803
- {
804
- name: "job:cancel",
805
- description: "Cancel a running or pending background job",
806
- argsSchema: z4.object({
807
- jobId: z4.string().min(1).describe("Job ID to cancel")
808
- }),
809
- handler: (args, context) => handleCancelJob(args, context)
810
- }
811
- ];
812
-
813
- // src/mcp/commands/meta.commands.ts
814
- import { z as z5 } from "zod";
815
- var metaCommands = [
907
+ // src/mcp/handlers/index.ts
908
+ var tools = [
816
909
  {
817
- name: "commands",
818
- description: "List all available commands",
819
- handler: () => {
820
- const commands = commandRegistry.all();
821
- const commandList = commands.map((cmd) => ({
822
- name: cmd.name,
823
- description: cmd.description
824
- }));
825
- return Promise.resolve({
826
- content: [
827
- {
828
- type: "text",
829
- text: JSON.stringify({ commands: commandList }, null, 2)
830
- }
831
- ]
832
- });
833
- }
910
+ name: "search",
911
+ description: "Search all indexed knowledge stores with pattern detection and AI-optimized results. Returns structured code units with progressive context layers.",
912
+ schema: SearchArgsSchema,
913
+ handler: handleSearch
834
914
  },
835
915
  {
836
- name: "help",
837
- description: "Show help for a specific command or list all commands",
838
- argsSchema: z5.object({
839
- command: z5.string().optional().describe("Command name to get help for")
840
- }),
841
- handler: (args) => {
842
- const commandName = args["command"];
843
- const helpText = generateHelp(commandName);
844
- return Promise.resolve({
845
- content: [
846
- {
847
- type: "text",
848
- text: helpText
849
- }
850
- ]
851
- });
852
- }
916
+ name: "get_full_context",
917
+ description: "Get complete code and context for a specific search result by ID. Use this after search to get full implementation details.",
918
+ schema: GetFullContextArgsSchema,
919
+ handler: handleGetFullContext
853
920
  }
854
921
  ];
855
922
 
856
- // src/mcp/commands/index.ts
857
- commandRegistry.registerAll(storeCommands);
858
- commandRegistry.registerAll(jobCommands);
859
- commandRegistry.registerAll(metaCommands);
860
-
861
- // src/mcp/handlers/execute.handler.ts
862
- var handleExecute = async (args, context) => {
863
- const validated = ExecuteArgsSchema.parse(args);
864
- const commandArgs = validated.args ?? {};
865
- return executeCommand(validated.command, commandArgs, context);
866
- };
867
-
868
923
  // src/mcp/server.ts
869
924
  var logger2 = createLogger("mcp-server");
870
925
  function createMCPServer(options) {
@@ -895,7 +950,13 @@ function createMCPServer(options) {
895
950
  },
896
951
  intent: {
897
952
  type: "string",
898
- enum: ["find-pattern", "find-implementation", "find-usage", "find-definition", "find-documentation"],
953
+ enum: [
954
+ "find-pattern",
955
+ "find-implementation",
956
+ "find-usage",
957
+ "find-definition",
958
+ "find-documentation"
959
+ ],
899
960
  description: "Search intent for better ranking"
900
961
  },
901
962
  detail: {
@@ -959,11 +1020,7 @@ function createMCPServer(options) {
959
1020
  const { name, arguments: args } = request.params;
960
1021
  const startTime = Date.now();
961
1022
  logger2.info({ tool: name, args: JSON.stringify(args) }, "Tool invoked");
962
- const services = await createServices(
963
- options.config,
964
- options.dataDir,
965
- options.projectRoot
966
- );
1023
+ const services = await createServices(options.config, options.dataDir, options.projectRoot);
967
1024
  const context = { services, options };
968
1025
  try {
969
1026
  let result;
@@ -983,21 +1040,27 @@ function createMCPServer(options) {
983
1040
  return result;
984
1041
  } catch (error) {
985
1042
  const durationMs = Date.now() - startTime;
986
- logger2.error({
987
- tool: name,
988
- durationMs,
989
- error: error instanceof Error ? error.message : String(error)
990
- }, "Tool execution failed");
1043
+ logger2.error(
1044
+ {
1045
+ tool: name,
1046
+ durationMs,
1047
+ error: error instanceof Error ? error.message : String(error)
1048
+ },
1049
+ "Tool execution failed"
1050
+ );
991
1051
  throw error;
992
1052
  }
993
1053
  });
994
1054
  return server;
995
1055
  }
996
1056
  async function runMCPServer(options) {
997
- logger2.info({
998
- dataDir: options.dataDir,
999
- projectRoot: options.projectRoot
1000
- }, "MCP server starting");
1057
+ logger2.info(
1058
+ {
1059
+ dataDir: options.dataDir,
1060
+ projectRoot: options.projectRoot
1061
+ },
1062
+ "MCP server starting"
1063
+ );
1001
1064
  const server = createMCPServer(options);
1002
1065
  const transport = new StdioServerTransport();
1003
1066
  await server.connect(transport);
@@ -1011,7 +1074,10 @@ if (isMCPServerEntry) {
1011
1074
  config: process.env["CONFIG_PATH"],
1012
1075
  projectRoot: process.env["PROJECT_ROOT"] ?? process.env["PWD"]
1013
1076
  }).catch((error) => {
1014
- logger2.error({ error: error instanceof Error ? error.message : String(error) }, "Failed to start MCP server");
1077
+ logger2.error(
1078
+ { error: error instanceof Error ? error.message : String(error) },
1079
+ "Failed to start MCP server"
1080
+ );
1015
1081
  process.exit(1);
1016
1082
  });
1017
1083
  }
@@ -1020,4 +1086,4 @@ export {
1020
1086
  createMCPServer,
1021
1087
  runMCPServer
1022
1088
  };
1023
- //# sourceMappingURL=chunk-WT2DAEO7.js.map
1089
+ //# sourceMappingURL=chunk-Z2KKVH45.js.map