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.
- package/.claude/hooks/post-edit-check.sh +5 -3
- package/.claude/skills/atomic-commits/SKILL.md +3 -1
- package/.husky/pre-commit +3 -2
- package/.prettierrc +9 -0
- package/.versionrc.json +1 -1
- package/CHANGELOG.md +33 -0
- package/CLAUDE.md +6 -0
- package/README.md +25 -13
- package/bun.lock +277 -33
- package/dist/{chunk-L2YVNC63.js → chunk-6FHWC36B.js} +9 -1
- package/dist/chunk-6FHWC36B.js.map +1 -0
- package/dist/{chunk-RST4XGRL.js → chunk-DC7CGSGT.js} +288 -241
- package/dist/chunk-DC7CGSGT.js.map +1 -0
- package/dist/{chunk-6PBP5DVD.js → chunk-WFNPNAAP.js} +3212 -3054
- package/dist/chunk-WFNPNAAP.js.map +1 -0
- package/dist/{chunk-WT2DAEO7.js → chunk-Z2KKVH45.js} +548 -482
- package/dist/chunk-Z2KKVH45.js.map +1 -0
- package/dist/index.js +871 -758
- package/dist/index.js.map +1 -1
- package/dist/mcp/server.js +3 -3
- package/dist/watch.service-BJV3TI3F.js +7 -0
- package/dist/workers/background-worker-cli.js +46 -45
- package/dist/workers/background-worker-cli.js.map +1 -1
- package/eslint.config.js +43 -1
- package/package.json +18 -11
- package/plugin.json +8 -0
- package/python/requirements.txt +1 -1
- package/src/analysis/ast-parser.test.ts +12 -11
- package/src/analysis/ast-parser.ts +28 -22
- package/src/analysis/code-graph.test.ts +52 -62
- package/src/analysis/code-graph.ts +9 -13
- package/src/analysis/dependency-usage-analyzer.test.ts +91 -271
- package/src/analysis/dependency-usage-analyzer.ts +52 -24
- package/src/analysis/go-ast-parser.test.ts +22 -22
- package/src/analysis/go-ast-parser.ts +18 -25
- package/src/analysis/parser-factory.test.ts +9 -9
- package/src/analysis/parser-factory.ts +3 -3
- package/src/analysis/python-ast-parser.test.ts +27 -27
- package/src/analysis/python-ast-parser.ts +2 -2
- package/src/analysis/repo-url-resolver.test.ts +82 -82
- package/src/analysis/rust-ast-parser.test.ts +19 -19
- package/src/analysis/rust-ast-parser.ts +17 -27
- package/src/analysis/tree-sitter-parser.test.ts +3 -3
- package/src/analysis/tree-sitter-parser.ts +10 -16
- package/src/cli/commands/crawl.test.ts +40 -24
- package/src/cli/commands/crawl.ts +186 -166
- package/src/cli/commands/index-cmd.test.ts +90 -90
- package/src/cli/commands/index-cmd.ts +52 -36
- package/src/cli/commands/mcp.test.ts +6 -6
- package/src/cli/commands/mcp.ts +2 -2
- package/src/cli/commands/plugin-api.test.ts +16 -18
- package/src/cli/commands/plugin-api.ts +9 -6
- package/src/cli/commands/search.test.ts +16 -7
- package/src/cli/commands/search.ts +124 -87
- package/src/cli/commands/serve.test.ts +67 -25
- package/src/cli/commands/serve.ts +18 -3
- package/src/cli/commands/setup.test.ts +176 -101
- package/src/cli/commands/setup.ts +140 -117
- package/src/cli/commands/store.test.ts +82 -53
- package/src/cli/commands/store.ts +56 -37
- package/src/cli/program.ts +2 -2
- package/src/crawl/article-converter.test.ts +4 -1
- package/src/crawl/article-converter.ts +46 -31
- package/src/crawl/bridge.test.ts +240 -132
- package/src/crawl/bridge.ts +87 -30
- package/src/crawl/claude-client.test.ts +124 -56
- package/src/crawl/claude-client.ts +7 -15
- package/src/crawl/intelligent-crawler.test.ts +65 -22
- package/src/crawl/intelligent-crawler.ts +86 -53
- package/src/crawl/markdown-utils.ts +1 -4
- package/src/db/embeddings.ts +4 -6
- package/src/db/lance.test.ts +4 -4
- package/src/db/lance.ts +16 -12
- package/src/index.ts +26 -17
- package/src/logging/index.ts +1 -5
- package/src/logging/logger.ts +3 -5
- package/src/logging/payload.test.ts +1 -1
- package/src/logging/payload.ts +3 -5
- package/src/mcp/commands/index.ts +2 -2
- package/src/mcp/commands/job.commands.ts +12 -18
- package/src/mcp/commands/meta.commands.ts +13 -13
- package/src/mcp/commands/registry.ts +5 -8
- package/src/mcp/commands/store.commands.ts +19 -19
- package/src/mcp/handlers/execute.handler.test.ts +10 -10
- package/src/mcp/handlers/execute.handler.ts +4 -5
- package/src/mcp/handlers/index.ts +10 -14
- package/src/mcp/handlers/job.handler.test.ts +10 -10
- package/src/mcp/handlers/job.handler.ts +22 -25
- package/src/mcp/handlers/search.handler.test.ts +36 -65
- package/src/mcp/handlers/search.handler.ts +135 -104
- package/src/mcp/handlers/store.handler.test.ts +41 -52
- package/src/mcp/handlers/store.handler.ts +108 -88
- package/src/mcp/schemas/index.test.ts +73 -68
- package/src/mcp/schemas/index.ts +18 -12
- package/src/mcp/server.test.ts +1 -1
- package/src/mcp/server.ts +59 -46
- package/src/plugin/commands.test.ts +230 -95
- package/src/plugin/commands.ts +24 -25
- package/src/plugin/dependency-analyzer.test.ts +52 -52
- package/src/plugin/dependency-analyzer.ts +85 -22
- package/src/plugin/git-clone.test.ts +24 -13
- package/src/plugin/git-clone.ts +3 -7
- package/src/server/app.test.ts +109 -109
- package/src/server/app.ts +32 -23
- package/src/server/index.test.ts +64 -66
- package/src/services/chunking.service.test.ts +32 -32
- package/src/services/chunking.service.ts +16 -9
- package/src/services/code-graph.service.test.ts +30 -36
- package/src/services/code-graph.service.ts +24 -10
- package/src/services/code-unit.service.test.ts +55 -11
- package/src/services/code-unit.service.ts +85 -11
- package/src/services/config.service.test.ts +37 -18
- package/src/services/config.service.ts +30 -7
- package/src/services/index.service.test.ts +49 -18
- package/src/services/index.service.ts +98 -48
- package/src/services/index.ts +6 -9
- package/src/services/job.service.test.ts +22 -22
- package/src/services/job.service.ts +18 -18
- package/src/services/project-root.service.test.ts +1 -3
- package/src/services/search.service.test.ts +248 -120
- package/src/services/search.service.ts +286 -156
- package/src/services/services.test.ts +1 -1
- package/src/services/snippet.service.test.ts +14 -6
- package/src/services/snippet.service.ts +7 -5
- package/src/services/store.service.test.ts +68 -29
- package/src/services/store.service.ts +41 -12
- package/src/services/watch.service.test.ts +34 -14
- package/src/services/watch.service.ts +11 -1
- package/src/types/brands.test.ts +3 -1
- package/src/types/index.ts +2 -13
- package/src/types/search.ts +10 -8
- package/src/utils/type-guards.test.ts +20 -15
- package/src/utils/type-guards.ts +1 -1
- package/src/workers/background-worker-cli.ts +2 -2
- package/src/workers/background-worker.test.ts +54 -40
- package/src/workers/background-worker.ts +76 -60
- package/src/workers/spawn-worker.test.ts +22 -10
- package/src/workers/spawn-worker.ts +6 -6
- package/tests/analysis/ast-parser.test.ts +3 -3
- package/tests/analysis/code-graph.test.ts +5 -5
- package/tests/fixtures/code-snippets/api/error-handling.ts +4 -15
- package/tests/fixtures/code-snippets/api/rest-controller.ts +3 -9
- package/tests/fixtures/code-snippets/auth/jwt-auth.ts +5 -21
- package/tests/fixtures/code-snippets/auth/oauth-flow.ts +4 -4
- package/tests/fixtures/code-snippets/database/repository-pattern.ts +11 -3
- package/tests/fixtures/corpus/oss-repos/hono/src/adapter/aws-lambda/handler.ts +2 -2
- package/tests/fixtures/corpus/oss-repos/hono/src/adapter/cloudflare-pages/handler.ts +1 -1
- package/tests/fixtures/corpus/oss-repos/hono/src/adapter/cloudflare-workers/serve-static.ts +2 -2
- package/tests/fixtures/corpus/oss-repos/hono/src/client/client.ts +2 -2
- package/tests/fixtures/corpus/oss-repos/hono/src/client/types.ts +22 -20
- package/tests/fixtures/corpus/oss-repos/hono/src/context.ts +13 -10
- package/tests/fixtures/corpus/oss-repos/hono/src/helper/accepts/accepts.ts +10 -7
- package/tests/fixtures/corpus/oss-repos/hono/src/helper/adapter/index.ts +2 -2
- package/tests/fixtures/corpus/oss-repos/hono/src/helper/css/index.ts +1 -1
- package/tests/fixtures/corpus/oss-repos/hono/src/helper/factory/index.ts +16 -16
- package/tests/fixtures/corpus/oss-repos/hono/src/helper/ssg/ssg.ts +2 -2
- package/tests/fixtures/corpus/oss-repos/hono/src/hono-base.ts +3 -3
- package/tests/fixtures/corpus/oss-repos/hono/src/hono.ts +1 -1
- package/tests/fixtures/corpus/oss-repos/hono/src/jsx/dom/css.ts +2 -2
- package/tests/fixtures/corpus/oss-repos/hono/src/jsx/dom/intrinsic-element/components.ts +1 -1
- package/tests/fixtures/corpus/oss-repos/hono/src/jsx/dom/render.ts +7 -7
- package/tests/fixtures/corpus/oss-repos/hono/src/jsx/hooks/index.ts +3 -3
- package/tests/fixtures/corpus/oss-repos/hono/src/jsx/intrinsic-element/components.ts +1 -1
- package/tests/fixtures/corpus/oss-repos/hono/src/jsx/utils.ts +6 -6
- package/tests/fixtures/corpus/oss-repos/hono/src/middleware/jsx-renderer/index.ts +3 -3
- package/tests/fixtures/corpus/oss-repos/hono/src/middleware/serve-static/index.ts +1 -1
- package/tests/fixtures/corpus/oss-repos/hono/src/preset/quick.ts +1 -1
- package/tests/fixtures/corpus/oss-repos/hono/src/preset/tiny.ts +1 -1
- package/tests/fixtures/corpus/oss-repos/hono/src/router/pattern-router/router.ts +2 -2
- package/tests/fixtures/corpus/oss-repos/hono/src/router/reg-exp-router/node.ts +4 -4
- package/tests/fixtures/corpus/oss-repos/hono/src/router/reg-exp-router/router.ts +1 -1
- package/tests/fixtures/corpus/oss-repos/hono/src/router/trie-router/node.ts +1 -1
- package/tests/fixtures/corpus/oss-repos/hono/src/types.ts +166 -169
- package/tests/fixtures/corpus/oss-repos/hono/src/utils/body.ts +8 -8
- package/tests/fixtures/corpus/oss-repos/hono/src/utils/color.ts +3 -3
- package/tests/fixtures/corpus/oss-repos/hono/src/utils/cookie.ts +2 -2
- package/tests/fixtures/corpus/oss-repos/hono/src/utils/encode.ts +2 -2
- package/tests/fixtures/corpus/oss-repos/hono/src/utils/types.ts +30 -33
- package/tests/fixtures/corpus/oss-repos/hono/src/validator/validator.ts +2 -2
- package/tests/fixtures/test-server.ts +3 -2
- package/tests/helpers/performance-metrics.ts +8 -25
- package/tests/helpers/search-relevance.ts +14 -69
- package/tests/integration/cli-consistency.test.ts +5 -4
- package/tests/integration/python-bridge.test.ts +13 -3
- package/tests/mcp/server.test.ts +1 -1
- package/tests/services/code-unit.service.test.ts +48 -0
- package/tests/services/job.service.test.ts +124 -0
- package/tests/services/search.progressive-context.test.ts +2 -2
- package/.claude-plugin/plugin.json +0 -13
- package/dist/chunk-6PBP5DVD.js.map +0 -1
- package/dist/chunk-L2YVNC63.js.map +0 -1
- package/dist/chunk-RST4XGRL.js.map +0 -1
- package/dist/chunk-WT2DAEO7.js.map +0 -1
- package/dist/watch.service-YAIKKDCF.js +0 -7
- package/skills/atomic-commits/SKILL.md +0 -77
- /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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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(() =>
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
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(() =>
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
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(() =>
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
});
|
package/src/mcp/schemas/index.ts
CHANGED
|
@@ -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([
|
|
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>;
|
package/src/mcp/server.test.ts
CHANGED
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:
|
|
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:
|
|
42
|
+
description:
|
|
43
|
+
'Search query (can include type signatures, constraints, or natural language)',
|
|
45
44
|
},
|
|
46
45
|
intent: {
|
|
47
46
|
type: 'string',
|
|
48
|
-
enum: [
|
|
49
|
-
|
|
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:
|
|
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:
|
|
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:
|
|
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
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
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
|
-
|
|
166
|
-
|
|
167
|
-
|
|
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(
|
|
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
|
}
|