@chiway/contextweaver 1.4.0 → 1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +138 -28
- package/dist/{SearchService-OS7CYHNJ.js → SearchService-WVD6THR3.js} +116 -74
- package/dist/{chunk-ZOMGPIU6.js → chunk-3BNHQV5W.js} +1 -5
- package/dist/chunk-BFCIZ52F.js +102 -0
- package/dist/{chunk-X7PAYQMT.js → chunk-GDVB6PJ4.js} +21 -3
- package/dist/{lock-FL54LIQL.js → chunk-HHYPQA3X.js} +1 -1
- package/dist/chunk-ISVCQFB4.js +223 -0
- package/dist/chunk-IZ6IUHNN.js +77 -0
- package/dist/chunk-LB42CZEB.js +18 -0
- package/dist/{chunk-RGJSXUFS.js → chunk-PPLFJGO3.js} +60 -0
- package/dist/chunk-R6CNZXZ7.js +143 -0
- package/dist/chunk-TPM6YP43.js +38 -0
- package/dist/{chunk-EMSMLPMK.js → chunk-V3K4YVAR.js} +10 -117
- package/dist/chunk-VWBKZ6QL.js +115 -0
- package/dist/chunk-XFIM2T6S.js +57 -0
- package/dist/{chunk-AB24E3Z7.js → chunk-XMZZZKG7.js} +23 -79
- package/dist/chunk-XTWNT7KP.js +156 -0
- package/dist/chunk-Y6H7C3NA.js +85 -0
- package/dist/{codebaseRetrieval-3Z4CRA7X.js → codebaseRetrieval-DIS5RH2C.js} +5 -2
- package/dist/{db-PMVM7557.js → db-GBCLP4GG.js} +15 -1
- package/dist/findReferences-N7ML7TUP.js +16 -0
- package/dist/getSymbolDefinition-6KMY4H33.js +17 -0
- package/dist/index.js +244 -41
- package/dist/listFiles-4VT2TPJD.js +14 -0
- package/dist/loadConfig-XTVT2OWW.js +9 -0
- package/dist/lock-HNKQ6X5B.js +8 -0
- package/dist/scanner-QDFZJLP7.js +13 -0
- package/dist/server-UAI3U7AB.js +347 -0
- package/dist/stats-AGKUCJQI.js +12 -0
- package/dist/{vectorStore-HPQZOVWF.js → vectorStore-4ODCERRO.js} +1 -1
- package/package.json +9 -23
- package/dist/scanner-2XGJWYHR.js +0 -11
- package/dist/server-XK6EINRV.js +0 -146
|
@@ -0,0 +1,347 @@
|
|
|
1
|
+
import {
|
|
2
|
+
findReferencesSchema,
|
|
3
|
+
handleFindReferences
|
|
4
|
+
} from "./chunk-R6CNZXZ7.js";
|
|
5
|
+
import {
|
|
6
|
+
codebaseRetrievalSchema,
|
|
7
|
+
handleCodebaseRetrieval
|
|
8
|
+
} from "./chunk-V3K4YVAR.js";
|
|
9
|
+
import {
|
|
10
|
+
collectStats,
|
|
11
|
+
renderStatsText
|
|
12
|
+
} from "./chunk-XTWNT7KP.js";
|
|
13
|
+
import {
|
|
14
|
+
handleListFiles,
|
|
15
|
+
listFilesSchema
|
|
16
|
+
} from "./chunk-Y6H7C3NA.js";
|
|
17
|
+
import {
|
|
18
|
+
getSymbolDefinitionSchema,
|
|
19
|
+
handleGetSymbolDefinition
|
|
20
|
+
} from "./chunk-ISVCQFB4.js";
|
|
21
|
+
import "./chunk-LB42CZEB.js";
|
|
22
|
+
import "./chunk-XFIM2T6S.js";
|
|
23
|
+
import "./chunk-3BNHQV5W.js";
|
|
24
|
+
import "./chunk-VWBKZ6QL.js";
|
|
25
|
+
import "./chunk-TPM6YP43.js";
|
|
26
|
+
import "./chunk-BFCIZ52F.js";
|
|
27
|
+
import {
|
|
28
|
+
generateProjectId
|
|
29
|
+
} from "./chunk-PPLFJGO3.js";
|
|
30
|
+
import {
|
|
31
|
+
logger
|
|
32
|
+
} from "./chunk-JVKVSTQ3.js";
|
|
33
|
+
import "./chunk-SKBAE26T.js";
|
|
34
|
+
|
|
35
|
+
// src/mcp/server.ts
|
|
36
|
+
import { existsSync, readFileSync } from "fs";
|
|
37
|
+
import { dirname, join } from "path";
|
|
38
|
+
import { fileURLToPath } from "url";
|
|
39
|
+
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
40
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
41
|
+
import { CallToolRequestSchema, ListToolsRequestSchema } from "@modelcontextprotocol/sdk/types.js";
|
|
42
|
+
|
|
43
|
+
// src/mcp/tools/stats.ts
|
|
44
|
+
import path from "path";
|
|
45
|
+
import { z } from "zod";
|
|
46
|
+
var statsToolSchema = z.object({
|
|
47
|
+
repo_path: z.string().describe(
|
|
48
|
+
"The absolute file system path to the repository root. (e.g., '/Users/dev/my-project')"
|
|
49
|
+
)
|
|
50
|
+
});
|
|
51
|
+
async function handleStats(args) {
|
|
52
|
+
const rootPath = path.resolve(args.repo_path);
|
|
53
|
+
const projectId = generateProjectId(rootPath);
|
|
54
|
+
const report = await collectStats(projectId);
|
|
55
|
+
return {
|
|
56
|
+
content: [{ type: "text", text: renderStatsText(report) }]
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// src/mcp/server.ts
|
|
61
|
+
var SERVER_NAME = "contextweaver";
|
|
62
|
+
function resolveServerVersion() {
|
|
63
|
+
let dir = dirname(fileURLToPath(import.meta.url));
|
|
64
|
+
for (let i = 0; i < 5; i++) {
|
|
65
|
+
const pkgPath = join(dir, "package.json");
|
|
66
|
+
if (existsSync(pkgPath)) {
|
|
67
|
+
try {
|
|
68
|
+
return JSON.parse(readFileSync(pkgPath, "utf8")).version ?? "0.0.0";
|
|
69
|
+
} catch {
|
|
70
|
+
break;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
dir = dirname(dir);
|
|
74
|
+
}
|
|
75
|
+
return "0.0.0";
|
|
76
|
+
}
|
|
77
|
+
var SERVER_VERSION = resolveServerVersion();
|
|
78
|
+
var TOOLS = [
|
|
79
|
+
{
|
|
80
|
+
name: "codebase-retrieval",
|
|
81
|
+
description: `
|
|
82
|
+
IMPORTANT: This is the PRIMARY tool for searching the codebase.
|
|
83
|
+
It uses a hybrid engine (Semantic + Exact Match) to find relevant code.
|
|
84
|
+
Think of it as the "Google Search" for this repository.
|
|
85
|
+
|
|
86
|
+
Capabilities:
|
|
87
|
+
1. Semantic Search: Understands "what code does" (e.g., "auth logic") via high-dimensional embeddings.
|
|
88
|
+
2. Exact Match: Filters by precise symbols (e.g., class names) via FTS (Full Text Search).
|
|
89
|
+
3. Localized Context: Returns code with localized context (breadcrumbs) to avoid token overflow.
|
|
90
|
+
|
|
91
|
+
<RULES>
|
|
92
|
+
# 1. Tool Selection (When to use)
|
|
93
|
+
- ALWAYS use this tool FIRST for any code exploration or understanding task.
|
|
94
|
+
- DO NOT try to guess file paths. If you don't have the exact path, use this tool.
|
|
95
|
+
- DO NOT use 'grep' or 'find' for semantic understanding. Only use them for exhaustive text matching (e.g. "Find ALL occurrences of string 'foo'").
|
|
96
|
+
|
|
97
|
+
# 2. Before Editing (Critical)
|
|
98
|
+
- Before creating a plan or editing any file, YOU MUST call this tool to gather context.
|
|
99
|
+
- Ask for ALL symbols involved in the edit (classes, functions, types, constants).
|
|
100
|
+
- Do not assume you remember the code structure. Verify it with this tool.
|
|
101
|
+
|
|
102
|
+
# 3. Query Strategy (How to use)
|
|
103
|
+
- Split your intent:
|
|
104
|
+
- Put the "Goal/Context" in 'information_request'.
|
|
105
|
+
- Put "Known Class/Func Names" in 'technical_terms'.
|
|
106
|
+
- If the first search is too broad, add more specific 'technical_terms'.
|
|
107
|
+
</RULES>
|
|
108
|
+
|
|
109
|
+
Examples of GOOD queries:
|
|
110
|
+
* [Goal: Understand Auth]
|
|
111
|
+
information_request: "How is user authentication flow handled?"
|
|
112
|
+
* [Goal: Fix DB Pool bug]
|
|
113
|
+
information_request: "Logic for database connection pooling and error handling"
|
|
114
|
+
technical_terms: ["PoolConfig", "Connection", "release"]
|
|
115
|
+
|
|
116
|
+
Examples of BAD queries:
|
|
117
|
+
* "Show me src/main.ts" (Use 'read_file' instead)
|
|
118
|
+
* "Find definition of constructor of class Foo" (Use this tool, but put "Foo" in technical_terms)
|
|
119
|
+
* "Find all references to function bar across the whole project" (Use 'grep' tool for exhaustive reference counting)
|
|
120
|
+
`,
|
|
121
|
+
inputSchema: {
|
|
122
|
+
type: "object",
|
|
123
|
+
properties: {
|
|
124
|
+
repo_path: {
|
|
125
|
+
type: "string",
|
|
126
|
+
description: "The absolute file system path to the repository root."
|
|
127
|
+
},
|
|
128
|
+
information_request: {
|
|
129
|
+
type: "string",
|
|
130
|
+
description: "The SEMANTIC GOAL. Describe the functionality, logic, or behavior you are looking for in full natural language sentences. Focus on 'how it works' rather than exact names. (e.g., 'Trace the execution flow of the login process')"
|
|
131
|
+
},
|
|
132
|
+
technical_terms: {
|
|
133
|
+
type: "array",
|
|
134
|
+
items: { type: "string" },
|
|
135
|
+
description: "HARD FILTERS. An optional list of EXACT, KNOWN identifiers (class/function names, constants) that MUST appear in the code. Only use terms you are 100% sure exist. Leave empty if exploring."
|
|
136
|
+
}
|
|
137
|
+
},
|
|
138
|
+
required: ["repo_path", "information_request"]
|
|
139
|
+
}
|
|
140
|
+
},
|
|
141
|
+
{
|
|
142
|
+
name: "stats",
|
|
143
|
+
description: `Show ContextWeaver index/search/health statistics for a repository.
|
|
144
|
+
|
|
145
|
+
Returns three sections:
|
|
146
|
+
1. Index process: last index run snapshot + cumulative run count.
|
|
147
|
+
2. Search quality/behavior: cumulative queries, cache hit rate, average per-stage latency (retrieve/rerank/expand/pack), average recall.
|
|
148
|
+
3. Health/consistency: file count, language breakdown, LanceDB vector row count, embedding dimensions, migration state, pending_marks, and cross-store consistency diagnostics.
|
|
149
|
+
|
|
150
|
+
Use this to inspect whether the index is healthy and how search is performing.`,
|
|
151
|
+
inputSchema: {
|
|
152
|
+
type: "object",
|
|
153
|
+
properties: {
|
|
154
|
+
repo_path: {
|
|
155
|
+
type: "string",
|
|
156
|
+
description: "The absolute file system path to the repository root."
|
|
157
|
+
}
|
|
158
|
+
},
|
|
159
|
+
required: ["repo_path"]
|
|
160
|
+
}
|
|
161
|
+
},
|
|
162
|
+
{
|
|
163
|
+
name: "list-files",
|
|
164
|
+
description: `List indexed files for quick structural exploration.
|
|
165
|
+
|
|
166
|
+
Use this when you want:
|
|
167
|
+
- repository structure
|
|
168
|
+
- file paths, languages, and sizes
|
|
169
|
+
- zero embedding API cost
|
|
170
|
+
|
|
171
|
+
This is a metadata view, not semantic retrieval.`,
|
|
172
|
+
inputSchema: {
|
|
173
|
+
type: "object",
|
|
174
|
+
properties: {
|
|
175
|
+
repo_path: {
|
|
176
|
+
type: "string",
|
|
177
|
+
description: "The absolute file system path to the repository root."
|
|
178
|
+
},
|
|
179
|
+
glob: {
|
|
180
|
+
type: "string",
|
|
181
|
+
description: "Optional glob pattern to filter returned file paths."
|
|
182
|
+
},
|
|
183
|
+
language: {
|
|
184
|
+
type: "string",
|
|
185
|
+
description: "Optional language filter matched against files.language."
|
|
186
|
+
},
|
|
187
|
+
max_results: {
|
|
188
|
+
type: "number",
|
|
189
|
+
description: "Maximum number of files to return. Defaults to 200."
|
|
190
|
+
}
|
|
191
|
+
},
|
|
192
|
+
required: ["repo_path"]
|
|
193
|
+
}
|
|
194
|
+
},
|
|
195
|
+
{
|
|
196
|
+
name: "find-references",
|
|
197
|
+
description: `Find heuristic text references to a known symbol across indexed chunks.
|
|
198
|
+
|
|
199
|
+
Use this when:
|
|
200
|
+
- you know the exact symbol name
|
|
201
|
+
- you want likely usage sites
|
|
202
|
+
|
|
203
|
+
Limits:
|
|
204
|
+
- heuristic text search, not compiler-accurate references
|
|
205
|
+
- for exhaustive raw text matching, use grep outside MCP`,
|
|
206
|
+
inputSchema: {
|
|
207
|
+
type: "object",
|
|
208
|
+
properties: {
|
|
209
|
+
repo_path: {
|
|
210
|
+
type: "string",
|
|
211
|
+
description: "The absolute file system path to the repository root."
|
|
212
|
+
},
|
|
213
|
+
symbol: {
|
|
214
|
+
type: "string",
|
|
215
|
+
description: "The exact symbol name to search for."
|
|
216
|
+
},
|
|
217
|
+
exclude_definition: {
|
|
218
|
+
type: "boolean",
|
|
219
|
+
description: "Exclude chunks whose breadcrumb tail matches the symbol name."
|
|
220
|
+
},
|
|
221
|
+
max_results: {
|
|
222
|
+
type: "number",
|
|
223
|
+
description: "Maximum number of references to return. Defaults to 50."
|
|
224
|
+
}
|
|
225
|
+
},
|
|
226
|
+
required: ["repo_path", "symbol"]
|
|
227
|
+
}
|
|
228
|
+
},
|
|
229
|
+
{
|
|
230
|
+
name: "get-symbol-definition",
|
|
231
|
+
description: `Find likely symbol definitions for a known symbol name.
|
|
232
|
+
|
|
233
|
+
Use this when:
|
|
234
|
+
- you know the exact symbol name
|
|
235
|
+
- you want the defining code block
|
|
236
|
+
|
|
237
|
+
Limits:
|
|
238
|
+
- heuristic definition lookup, not compiler-accurate navigation
|
|
239
|
+
- ranks breadcrumb matches first, then definition-pattern FTS fallback`,
|
|
240
|
+
inputSchema: {
|
|
241
|
+
type: "object",
|
|
242
|
+
properties: {
|
|
243
|
+
repo_path: {
|
|
244
|
+
type: "string",
|
|
245
|
+
description: "The absolute file system path to the repository root."
|
|
246
|
+
},
|
|
247
|
+
symbol: {
|
|
248
|
+
type: "string",
|
|
249
|
+
description: "The exact symbol name to resolve."
|
|
250
|
+
},
|
|
251
|
+
hint_path: {
|
|
252
|
+
type: "string",
|
|
253
|
+
description: "Optional preferred path used to disambiguate same-name definitions."
|
|
254
|
+
},
|
|
255
|
+
max_results: {
|
|
256
|
+
type: "number",
|
|
257
|
+
description: "Maximum number of definitions to return. Defaults to 3."
|
|
258
|
+
}
|
|
259
|
+
},
|
|
260
|
+
required: ["repo_path", "symbol"]
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
];
|
|
264
|
+
async function startMcpServer() {
|
|
265
|
+
logger.info({ name: SERVER_NAME }, "\u542F\u52A8 MCP \u670D\u52A1\u5668");
|
|
266
|
+
const server = new Server(
|
|
267
|
+
{
|
|
268
|
+
name: SERVER_NAME,
|
|
269
|
+
version: SERVER_VERSION
|
|
270
|
+
},
|
|
271
|
+
{
|
|
272
|
+
capabilities: {
|
|
273
|
+
tools: {}
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
);
|
|
277
|
+
server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
278
|
+
logger.debug("\u6536\u5230 list_tools \u8BF7\u6C42");
|
|
279
|
+
return { tools: TOOLS };
|
|
280
|
+
});
|
|
281
|
+
server.setRequestHandler(CallToolRequestSchema, async (request, extra) => {
|
|
282
|
+
const { name, arguments: args } = request.params;
|
|
283
|
+
logger.info({ tool: name }, "\u6536\u5230 call_tool \u8BF7\u6C42");
|
|
284
|
+
const rawToken = extra._meta?.progressToken;
|
|
285
|
+
const progressToken = typeof rawToken === "string" || typeof rawToken === "number" ? rawToken : void 0;
|
|
286
|
+
const onProgress = progressToken ? async (current, total, message) => {
|
|
287
|
+
try {
|
|
288
|
+
await extra.sendNotification({
|
|
289
|
+
method: "notifications/progress",
|
|
290
|
+
params: {
|
|
291
|
+
progressToken,
|
|
292
|
+
progress: current,
|
|
293
|
+
total,
|
|
294
|
+
message
|
|
295
|
+
}
|
|
296
|
+
});
|
|
297
|
+
} catch (err) {
|
|
298
|
+
logger.debug({ error: err.message }, "\u53D1\u9001\u8FDB\u5EA6\u901A\u77E5\u5931\u8D25");
|
|
299
|
+
}
|
|
300
|
+
} : void 0;
|
|
301
|
+
try {
|
|
302
|
+
switch (name) {
|
|
303
|
+
case "codebase-retrieval": {
|
|
304
|
+
const parsed = codebaseRetrievalSchema.parse(args);
|
|
305
|
+
return await handleCodebaseRetrieval(parsed, onProgress);
|
|
306
|
+
}
|
|
307
|
+
case "stats": {
|
|
308
|
+
const parsed = statsToolSchema.parse(args);
|
|
309
|
+
return await handleStats(parsed);
|
|
310
|
+
}
|
|
311
|
+
case "list-files": {
|
|
312
|
+
const parsed = listFilesSchema.parse(args);
|
|
313
|
+
return await handleListFiles(parsed, onProgress);
|
|
314
|
+
}
|
|
315
|
+
case "find-references": {
|
|
316
|
+
const parsed = findReferencesSchema.parse(args);
|
|
317
|
+
return await handleFindReferences(parsed, onProgress);
|
|
318
|
+
}
|
|
319
|
+
case "get-symbol-definition": {
|
|
320
|
+
const parsed = getSymbolDefinitionSchema.parse(args);
|
|
321
|
+
return await handleGetSymbolDefinition(parsed, onProgress);
|
|
322
|
+
}
|
|
323
|
+
default:
|
|
324
|
+
throw new Error(`Unknown tool: ${name}`);
|
|
325
|
+
}
|
|
326
|
+
} catch (err) {
|
|
327
|
+
const error = err;
|
|
328
|
+
logger.error({ error: error.message, stack: error.stack, tool: name }, "\u5DE5\u5177\u8C03\u7528\u5931\u8D25");
|
|
329
|
+
return {
|
|
330
|
+
content: [
|
|
331
|
+
{
|
|
332
|
+
type: "text",
|
|
333
|
+
text: `Error: ${error.message}`
|
|
334
|
+
}
|
|
335
|
+
],
|
|
336
|
+
isError: true
|
|
337
|
+
};
|
|
338
|
+
}
|
|
339
|
+
});
|
|
340
|
+
const transport = new StdioServerTransport();
|
|
341
|
+
logger.info("MCP \u670D\u52A1\u5668\u5DF2\u542F\u52A8\uFF0C\u7B49\u5F85\u8FDE\u63A5...");
|
|
342
|
+
await server.connect(transport);
|
|
343
|
+
}
|
|
344
|
+
export {
|
|
345
|
+
TOOLS,
|
|
346
|
+
startMcpServer
|
|
347
|
+
};
|
package/package.json
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@chiway/contextweaver",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.5.0",
|
|
4
4
|
"description": "A context weaving tool for LLMs",
|
|
5
5
|
"license": "MIT",
|
|
6
|
-
"author": "
|
|
6
|
+
"author": "chiway",
|
|
7
7
|
"repository": {
|
|
8
8
|
"type": "git",
|
|
9
|
-
"url": "git+https://github.com/
|
|
9
|
+
"url": "git+https://github.com/wchiway/contextweaver-mcp.git"
|
|
10
10
|
},
|
|
11
|
-
"homepage": "https://github.com/
|
|
11
|
+
"homepage": "https://github.com/wchiway/contextweaver-mcp#readme",
|
|
12
12
|
"private": false,
|
|
13
13
|
"type": "module",
|
|
14
14
|
"bin": {
|
|
@@ -23,10 +23,12 @@
|
|
|
23
23
|
"node": ">=20"
|
|
24
24
|
},
|
|
25
25
|
"scripts": {
|
|
26
|
-
"build": "tsup src/index.ts
|
|
27
|
-
"build:release": "tsup src/index.ts
|
|
28
|
-
"dev": "tsup src/index.ts
|
|
26
|
+
"build": "tsup src/index.ts --format esm --dts --out-dir dist --sourcemap --clean",
|
|
27
|
+
"build:release": "tsup src/index.ts --format esm --dts --out-dir dist --clean",
|
|
28
|
+
"dev": "tsup src/index.ts --format esm --dts --out-dir dist --sourcemap --watch",
|
|
29
29
|
"fmt": "biome check --write ./src",
|
|
30
|
+
"lint": "biome check ./src",
|
|
31
|
+
"typecheck": "tsc --noEmit",
|
|
30
32
|
"test": "vitest run"
|
|
31
33
|
},
|
|
32
34
|
"dependencies": {
|
|
@@ -61,21 +63,5 @@
|
|
|
61
63
|
"tsup": "^8.5.1",
|
|
62
64
|
"typescript": "^5.9.3",
|
|
63
65
|
"vitest": "^4.1.0"
|
|
64
|
-
},
|
|
65
|
-
"pnpm": {
|
|
66
|
-
"onlyBuiltDependencies": [
|
|
67
|
-
"@keqingmoe/tree-sitter",
|
|
68
|
-
"better-sqlite3",
|
|
69
|
-
"esbuild",
|
|
70
|
-
"tree-sitter-c",
|
|
71
|
-
"tree-sitter-c-sharp",
|
|
72
|
-
"tree-sitter-cpp",
|
|
73
|
-
"tree-sitter-go",
|
|
74
|
-
"tree-sitter-java",
|
|
75
|
-
"tree-sitter-javascript",
|
|
76
|
-
"tree-sitter-python",
|
|
77
|
-
"tree-sitter-rust",
|
|
78
|
-
"tree-sitter-typescript"
|
|
79
|
-
]
|
|
80
66
|
}
|
|
81
67
|
}
|
package/dist/scanner-2XGJWYHR.js
DELETED
package/dist/server-XK6EINRV.js
DELETED
|
@@ -1,146 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
codebaseRetrievalSchema,
|
|
3
|
-
handleCodebaseRetrieval
|
|
4
|
-
} from "./chunk-EMSMLPMK.js";
|
|
5
|
-
import "./chunk-RGJSXUFS.js";
|
|
6
|
-
import {
|
|
7
|
-
logger
|
|
8
|
-
} from "./chunk-JVKVSTQ3.js";
|
|
9
|
-
import "./chunk-SKBAE26T.js";
|
|
10
|
-
|
|
11
|
-
// src/mcp/server.ts
|
|
12
|
-
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
13
|
-
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
14
|
-
import { CallToolRequestSchema, ListToolsRequestSchema } from "@modelcontextprotocol/sdk/types.js";
|
|
15
|
-
var SERVER_NAME = "contextweaver";
|
|
16
|
-
var TOOLS = [
|
|
17
|
-
{
|
|
18
|
-
name: "codebase-retrieval",
|
|
19
|
-
description: `
|
|
20
|
-
IMPORTANT: This is the PRIMARY tool for searching the codebase.
|
|
21
|
-
It uses a hybrid engine (Semantic + Exact Match) to find relevant code.
|
|
22
|
-
Think of it as the "Google Search" for this repository.
|
|
23
|
-
|
|
24
|
-
Capabilities:
|
|
25
|
-
1. Semantic Search: Understands "what code does" (e.g., "auth logic") via high-dimensional embeddings.
|
|
26
|
-
2. Exact Match: Filters by precise symbols (e.g., class names) via FTS (Full Text Search).
|
|
27
|
-
3. Localized Context: Returns code with localized context (breadcrumbs) to avoid token overflow.
|
|
28
|
-
|
|
29
|
-
<RULES>
|
|
30
|
-
# 1. Tool Selection (When to use)
|
|
31
|
-
- ALWAYS use this tool FIRST for any code exploration or understanding task.
|
|
32
|
-
- DO NOT try to guess file paths. If you don't have the exact path, use this tool.
|
|
33
|
-
- DO NOT use 'grep' or 'find' for semantic understanding. Only use them for exhaustive text matching (e.g. "Find ALL occurrences of string 'foo'").
|
|
34
|
-
|
|
35
|
-
# 2. Before Editing (Critical)
|
|
36
|
-
- Before creating a plan or editing any file, YOU MUST call this tool to gather context.
|
|
37
|
-
- Ask for ALL symbols involved in the edit (classes, functions, types, constants).
|
|
38
|
-
- Do not assume you remember the code structure. Verify it with this tool.
|
|
39
|
-
|
|
40
|
-
# 3. Query Strategy (How to use)
|
|
41
|
-
- Split your intent:
|
|
42
|
-
- Put the "Goal/Context" in 'information_request'.
|
|
43
|
-
- Put "Known Class/Func Names" in 'technical_terms'.
|
|
44
|
-
- If the first search is too broad, add more specific 'technical_terms'.
|
|
45
|
-
</RULES>
|
|
46
|
-
|
|
47
|
-
Examples of GOOD queries:
|
|
48
|
-
* [Goal: Understand Auth]
|
|
49
|
-
information_request: "How is user authentication flow handled?"
|
|
50
|
-
* [Goal: Fix DB Pool bug]
|
|
51
|
-
information_request: "Logic for database connection pooling and error handling"
|
|
52
|
-
technical_terms: ["PoolConfig", "Connection", "release"]
|
|
53
|
-
|
|
54
|
-
Examples of BAD queries:
|
|
55
|
-
* "Show me src/main.ts" (Use 'read_file' instead)
|
|
56
|
-
* "Find definition of constructor of class Foo" (Use this tool, but put "Foo" in technical_terms)
|
|
57
|
-
* "Find all references to function bar across the whole project" (Use 'grep' tool for exhaustive reference counting)
|
|
58
|
-
`,
|
|
59
|
-
inputSchema: {
|
|
60
|
-
type: "object",
|
|
61
|
-
properties: {
|
|
62
|
-
repo_path: {
|
|
63
|
-
type: "string",
|
|
64
|
-
description: "The absolute file system path to the repository root."
|
|
65
|
-
},
|
|
66
|
-
information_request: {
|
|
67
|
-
type: "string",
|
|
68
|
-
description: "The SEMANTIC GOAL. Describe the functionality, logic, or behavior you are looking for in full natural language sentences. Focus on 'how it works' rather than exact names. (e.g., 'Trace the execution flow of the login process')"
|
|
69
|
-
},
|
|
70
|
-
technical_terms: {
|
|
71
|
-
type: "array",
|
|
72
|
-
items: { type: "string" },
|
|
73
|
-
description: "HARD FILTERS. An optional list of EXACT, KNOWN identifiers (class/function names, constants) that MUST appear in the code. Only use terms you are 100% sure exist. Leave empty if exploring."
|
|
74
|
-
}
|
|
75
|
-
},
|
|
76
|
-
required: ["repo_path", "information_request"]
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
];
|
|
80
|
-
async function startMcpServer() {
|
|
81
|
-
logger.info({ name: SERVER_NAME }, "\u542F\u52A8 MCP \u670D\u52A1\u5668");
|
|
82
|
-
const server = new Server(
|
|
83
|
-
{
|
|
84
|
-
name: SERVER_NAME,
|
|
85
|
-
version: "1.0.0"
|
|
86
|
-
},
|
|
87
|
-
{
|
|
88
|
-
capabilities: {
|
|
89
|
-
tools: {}
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
);
|
|
93
|
-
server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
94
|
-
logger.debug("\u6536\u5230 list_tools \u8BF7\u6C42");
|
|
95
|
-
return { tools: TOOLS };
|
|
96
|
-
});
|
|
97
|
-
server.setRequestHandler(CallToolRequestSchema, async (request, extra) => {
|
|
98
|
-
const { name, arguments: args } = request.params;
|
|
99
|
-
logger.info({ tool: name }, "\u6536\u5230 call_tool \u8BF7\u6C42");
|
|
100
|
-
const rawToken = extra._meta?.progressToken;
|
|
101
|
-
const progressToken = typeof rawToken === "string" || typeof rawToken === "number" ? rawToken : void 0;
|
|
102
|
-
const onProgress = progressToken ? async (current, total, message) => {
|
|
103
|
-
try {
|
|
104
|
-
await extra.sendNotification({
|
|
105
|
-
method: "notifications/progress",
|
|
106
|
-
params: {
|
|
107
|
-
progressToken,
|
|
108
|
-
progress: current,
|
|
109
|
-
total,
|
|
110
|
-
message
|
|
111
|
-
}
|
|
112
|
-
});
|
|
113
|
-
} catch (err) {
|
|
114
|
-
logger.debug({ error: err.message }, "\u53D1\u9001\u8FDB\u5EA6\u901A\u77E5\u5931\u8D25");
|
|
115
|
-
}
|
|
116
|
-
} : void 0;
|
|
117
|
-
try {
|
|
118
|
-
switch (name) {
|
|
119
|
-
case "codebase-retrieval": {
|
|
120
|
-
const parsed = codebaseRetrievalSchema.parse(args);
|
|
121
|
-
return await handleCodebaseRetrieval(parsed, onProgress);
|
|
122
|
-
}
|
|
123
|
-
default:
|
|
124
|
-
throw new Error(`Unknown tool: ${name}`);
|
|
125
|
-
}
|
|
126
|
-
} catch (err) {
|
|
127
|
-
const error = err;
|
|
128
|
-
logger.error({ error: error.message, stack: error.stack, tool: name }, "\u5DE5\u5177\u8C03\u7528\u5931\u8D25");
|
|
129
|
-
return {
|
|
130
|
-
content: [
|
|
131
|
-
{
|
|
132
|
-
type: "text",
|
|
133
|
-
text: `Error: ${error.message}`
|
|
134
|
-
}
|
|
135
|
-
],
|
|
136
|
-
isError: true
|
|
137
|
-
};
|
|
138
|
-
}
|
|
139
|
-
});
|
|
140
|
-
const transport = new StdioServerTransport();
|
|
141
|
-
logger.info("MCP \u670D\u52A1\u5668\u5DF2\u542F\u52A8\uFF0C\u7B49\u5F85\u8FDE\u63A5...");
|
|
142
|
-
await server.connect(transport);
|
|
143
|
-
}
|
|
144
|
-
export {
|
|
145
|
-
startMcpServer
|
|
146
|
-
};
|