mcp-probe-kit 1.2.7 → 1.2.8
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/build/index.js +2 -2
- package/build/tools/analyze_project.js +106 -17
- package/package.json +1 -1
package/build/index.js
CHANGED
|
@@ -6,7 +6,7 @@ import { detectShell, initSetting, initProject, gencommit, debug, genapi, codeRe
|
|
|
6
6
|
// 创建MCP服务器实例
|
|
7
7
|
const server = new Server({
|
|
8
8
|
name: "mcp-probe-kit",
|
|
9
|
-
version: "1.2.
|
|
9
|
+
version: "1.2.8",
|
|
10
10
|
}, {
|
|
11
11
|
capabilities: {
|
|
12
12
|
tools: {},
|
|
@@ -528,7 +528,7 @@ server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
|
|
|
528
528
|
timestamp: new Date().toISOString(),
|
|
529
529
|
serverInfo: {
|
|
530
530
|
name: "mcp-probe-kit",
|
|
531
|
-
version: "1.2.
|
|
531
|
+
version: "1.2.8",
|
|
532
532
|
description: "Cursor 开发增强工具集",
|
|
533
533
|
},
|
|
534
534
|
tools: {
|
|
@@ -5,6 +5,7 @@ export async function analyzeProject(args) {
|
|
|
5
5
|
const maxDepth = args.max_depth || 5;
|
|
6
6
|
const includeContent = args.include_content !== false;
|
|
7
7
|
try {
|
|
8
|
+
console.error(`开始分析项目: ${projectPath}`);
|
|
8
9
|
const analysis = await performProjectAnalysis(projectPath, maxDepth, includeContent);
|
|
9
10
|
return {
|
|
10
11
|
content: [
|
|
@@ -42,8 +43,14 @@ ${analysis.dependencies.production.slice(0, 10).map(dep => `- ${dep}`).join('\n'
|
|
|
42
43
|
## 📈 代码指标
|
|
43
44
|
- **总文件数**: ${analysis.codeMetrics.totalFiles}
|
|
44
45
|
- **总行数**: ${analysis.codeMetrics.totalLines}
|
|
46
|
+
${analysis.codeMetrics.skippedFiles > 0 ? `- **跳过文件**: ${analysis.codeMetrics.skippedFiles} 个(过大或无法读取)` : ''}
|
|
45
47
|
- **文件类型分布**:
|
|
46
|
-
${Object.entries(analysis.codeMetrics.fileTypes)
|
|
48
|
+
${Object.entries(analysis.codeMetrics.fileTypes)
|
|
49
|
+
.sort(([, a], [, b]) => b - a)
|
|
50
|
+
.slice(0, 10)
|
|
51
|
+
.map(([type, count]) => ` - ${type}: ${count} 个文件`)
|
|
52
|
+
.join('\n')}
|
|
53
|
+
${Object.keys(analysis.codeMetrics.fileTypes).length > 10 ? ' - ... (更多类型已省略)' : ''}
|
|
47
54
|
|
|
48
55
|
### 最大文件
|
|
49
56
|
${analysis.codeMetrics.largestFiles.slice(0, 5).map(file => `- ${file.path} (${file.lines} 行)`).join('\n')}
|
|
@@ -61,7 +68,12 @@ ${analysis.summary.recommendations.map(rec => `- ${rec}`).join('\n')}
|
|
|
61
68
|
|
|
62
69
|
---
|
|
63
70
|
*分析完成时间: ${new Date().toLocaleString('zh-CN')}*
|
|
64
|
-
*分析工具: MCP Probe Kit v1.2.
|
|
71
|
+
*分析工具: MCP Probe Kit v1.2.8*
|
|
72
|
+
|
|
73
|
+
**分析说明**:
|
|
74
|
+
- 大型项目会自动采样分析,限制最多扫描 5000 个文件
|
|
75
|
+
- 已自动忽略以下目录: \`node_modules\`, \`dist\`, \`build\`, \`.git\`, \`coverage\`, \`.next\`, \`.nuxt\`, \`vendor\` 等
|
|
76
|
+
- 单个文件大小限制: 1MB,超过则跳过`,
|
|
65
77
|
},
|
|
66
78
|
],
|
|
67
79
|
};
|
|
@@ -181,19 +193,34 @@ function detectPackageManager() {
|
|
|
181
193
|
return 'npm';
|
|
182
194
|
}
|
|
183
195
|
function generateDirectoryTree(projectPath, maxDepth) {
|
|
184
|
-
const ignoreDirs = [
|
|
196
|
+
const ignoreDirs = [
|
|
197
|
+
'node_modules', '.git', 'dist', 'build', '.next', '.nuxt',
|
|
198
|
+
'coverage', '.vscode', '.idea', 'tmp', 'temp', 'out',
|
|
199
|
+
'vendor', '__pycache__', '.cache', '.parcel-cache',
|
|
200
|
+
'bower_components', 'jspm_packages'
|
|
201
|
+
];
|
|
202
|
+
const MAX_ITEMS_PER_DIR = 50; // 每个目录最多显示50项
|
|
185
203
|
function buildTree(dir, prefix = '', depth = 0) {
|
|
186
204
|
if (depth >= maxDepth)
|
|
187
205
|
return '';
|
|
188
206
|
try {
|
|
189
|
-
|
|
207
|
+
let items = readdirSync(dir)
|
|
190
208
|
.filter(item => !ignoreDirs.includes(item) && !item.startsWith('.'))
|
|
191
209
|
.map(item => {
|
|
192
210
|
const fullPath = join(dir, item);
|
|
193
|
-
|
|
194
|
-
|
|
211
|
+
try {
|
|
212
|
+
const stat = statSync(fullPath);
|
|
213
|
+
return { name: item, isDir: stat.isDirectory(), path: fullPath };
|
|
214
|
+
}
|
|
215
|
+
catch {
|
|
216
|
+
return null;
|
|
217
|
+
}
|
|
195
218
|
})
|
|
196
|
-
.
|
|
219
|
+
.filter(item => item !== null);
|
|
220
|
+
// 限制每个目录显示的项目数量
|
|
221
|
+
const hasMore = items.length > MAX_ITEMS_PER_DIR;
|
|
222
|
+
items = items.slice(0, MAX_ITEMS_PER_DIR);
|
|
223
|
+
items.sort((a, b) => {
|
|
197
224
|
if (a.isDir && !b.isDir)
|
|
198
225
|
return -1;
|
|
199
226
|
if (!a.isDir && b.isDir)
|
|
@@ -202,7 +229,7 @@ function generateDirectoryTree(projectPath, maxDepth) {
|
|
|
202
229
|
});
|
|
203
230
|
let result = '';
|
|
204
231
|
items.forEach((item, index) => {
|
|
205
|
-
const isLast = index === items.length - 1;
|
|
232
|
+
const isLast = index === items.length - 1 && !hasMore;
|
|
206
233
|
const currentPrefix = isLast ? '└── ' : '├── ';
|
|
207
234
|
const nextPrefix = isLast ? ' ' : '│ ';
|
|
208
235
|
result += `${prefix}${currentPrefix}${item.name}\n`;
|
|
@@ -210,6 +237,9 @@ function generateDirectoryTree(projectPath, maxDepth) {
|
|
|
210
237
|
result += buildTree(item.path, prefix + nextPrefix, depth + 1);
|
|
211
238
|
}
|
|
212
239
|
});
|
|
240
|
+
if (hasMore) {
|
|
241
|
+
result += `${prefix}└── ... (更多项目被省略)\n`;
|
|
242
|
+
}
|
|
213
243
|
return result;
|
|
214
244
|
}
|
|
215
245
|
catch {
|
|
@@ -225,12 +255,31 @@ async function identifyKeyFiles(projectPath, includeContent) {
|
|
|
225
255
|
'webpack.config.js', 'vite.config.js', 'next.config.js', 'nuxt.config.js',
|
|
226
256
|
'tsconfig.json', 'babel.config.js', '.env', '.env.example'
|
|
227
257
|
];
|
|
258
|
+
const MAX_FILE_SIZE = 100 * 1024; // 100KB
|
|
259
|
+
const MAX_CONTENT_LINES = 100; // 最多显示100行
|
|
228
260
|
const keyFiles = [];
|
|
229
261
|
for (const pattern of keyFilePatterns) {
|
|
230
262
|
try {
|
|
231
263
|
const filePath = join(projectPath, pattern);
|
|
232
|
-
const
|
|
264
|
+
const stat = statSync(filePath);
|
|
265
|
+
// 跳过过大的文件
|
|
266
|
+
if (stat.size > MAX_FILE_SIZE) {
|
|
267
|
+
keyFiles.push({
|
|
268
|
+
path: pattern,
|
|
269
|
+
purpose: getFilePurpose(pattern, ''),
|
|
270
|
+
content: includeContent ? `[文件过大 (${Math.round(stat.size / 1024)}KB),已跳过]` : ''
|
|
271
|
+
});
|
|
272
|
+
continue;
|
|
273
|
+
}
|
|
274
|
+
let content = readFileSync(filePath, 'utf-8');
|
|
233
275
|
const purpose = getFilePurpose(pattern, content);
|
|
276
|
+
// 限制内容行数
|
|
277
|
+
if (includeContent && content) {
|
|
278
|
+
const lines = content.split('\n');
|
|
279
|
+
if (lines.length > MAX_CONTENT_LINES) {
|
|
280
|
+
content = lines.slice(0, MAX_CONTENT_LINES).join('\n') + `\n... (省略 ${lines.length - MAX_CONTENT_LINES} 行)`;
|
|
281
|
+
}
|
|
282
|
+
}
|
|
234
283
|
keyFiles.push({
|
|
235
284
|
path: pattern,
|
|
236
285
|
purpose,
|
|
@@ -280,16 +329,39 @@ function analyzeDependencies(packageJson) {
|
|
|
280
329
|
async function calculateCodeMetrics(projectPath) {
|
|
281
330
|
const fileTypes = {};
|
|
282
331
|
const largestFiles = [];
|
|
332
|
+
const MAX_FILES_TO_SCAN = 5000; // 最多扫描5000个文件
|
|
333
|
+
const MAX_FILE_SIZE = 1 * 1024 * 1024; // 1MB
|
|
334
|
+
const SAMPLE_LARGE_PROJECTS = true; // 大项目采样
|
|
283
335
|
let totalFiles = 0;
|
|
284
336
|
let totalLines = 0;
|
|
337
|
+
let skippedFiles = 0;
|
|
338
|
+
let scannedFiles = 0;
|
|
285
339
|
function scanDirectory(dir) {
|
|
340
|
+
// 达到文件数量限制
|
|
341
|
+
if (scannedFiles >= MAX_FILES_TO_SCAN) {
|
|
342
|
+
return;
|
|
343
|
+
}
|
|
286
344
|
try {
|
|
287
345
|
const items = readdirSync(dir);
|
|
288
346
|
for (const item of items) {
|
|
347
|
+
if (scannedFiles >= MAX_FILES_TO_SCAN)
|
|
348
|
+
break;
|
|
289
349
|
const fullPath = join(dir, item);
|
|
290
|
-
|
|
350
|
+
let stat;
|
|
351
|
+
try {
|
|
352
|
+
stat = statSync(fullPath);
|
|
353
|
+
}
|
|
354
|
+
catch {
|
|
355
|
+
continue;
|
|
356
|
+
}
|
|
291
357
|
if (stat.isDirectory()) {
|
|
292
|
-
|
|
358
|
+
const ignoreDirs = [
|
|
359
|
+
'node_modules', '.git', 'dist', 'build', '.next', '.nuxt',
|
|
360
|
+
'coverage', '.vscode', '.idea', 'tmp', 'temp', 'out',
|
|
361
|
+
'vendor', '__pycache__', '.cache', '.parcel-cache',
|
|
362
|
+
'bower_components', 'jspm_packages', 'target', 'bin', 'obj'
|
|
363
|
+
];
|
|
364
|
+
if (!ignoreDirs.includes(item) && !item.startsWith('.')) {
|
|
293
365
|
scanDirectory(fullPath);
|
|
294
366
|
}
|
|
295
367
|
}
|
|
@@ -298,14 +370,27 @@ async function calculateCodeMetrics(projectPath) {
|
|
|
298
370
|
const fileType = ext || 'no-extension';
|
|
299
371
|
fileTypes[fileType] = (fileTypes[fileType] || 0) + 1;
|
|
300
372
|
totalFiles++;
|
|
373
|
+
scannedFiles++;
|
|
374
|
+
// 跳过过大的文件
|
|
375
|
+
if (stat.size > MAX_FILE_SIZE) {
|
|
376
|
+
skippedFiles++;
|
|
377
|
+
continue;
|
|
378
|
+
}
|
|
301
379
|
try {
|
|
302
|
-
|
|
303
|
-
const
|
|
304
|
-
|
|
305
|
-
|
|
380
|
+
// 只读取文本文件
|
|
381
|
+
const textExtensions = ['.js', '.ts', '.jsx', '.tsx', '.vue', '.py', '.java', '.go', '.rs', '.php', '.rb', '.cpp', '.c', '.h', '.cs', '.swift', '.kt'];
|
|
382
|
+
if (textExtensions.includes(ext.toLowerCase())) {
|
|
383
|
+
const content = readFileSync(fullPath, 'utf-8');
|
|
384
|
+
const lines = content.split('\n').length;
|
|
385
|
+
totalLines += lines;
|
|
386
|
+
// 只保存相对路径
|
|
387
|
+
const relativePath = fullPath.replace(projectPath, '').replace(/\\/g, '/');
|
|
388
|
+
largestFiles.push({ path: relativePath, lines });
|
|
389
|
+
}
|
|
306
390
|
}
|
|
307
391
|
catch {
|
|
308
|
-
//
|
|
392
|
+
// 忽略无法读取的文件(二进制文件等)
|
|
393
|
+
skippedFiles++;
|
|
309
394
|
}
|
|
310
395
|
}
|
|
311
396
|
}
|
|
@@ -314,14 +399,18 @@ async function calculateCodeMetrics(projectPath) {
|
|
|
314
399
|
// 忽略无法访问的目录
|
|
315
400
|
}
|
|
316
401
|
}
|
|
402
|
+
console.error('开始扫描代码文件...');
|
|
403
|
+
console.error('忽略目录: node_modules, dist, build, .git 等');
|
|
317
404
|
scanDirectory(projectPath);
|
|
405
|
+
console.error(`扫描完成: ${totalFiles} 个文件, ${skippedFiles} 个跳过`);
|
|
318
406
|
// 按行数排序,取前10个
|
|
319
407
|
largestFiles.sort((a, b) => b.lines - a.lines);
|
|
320
408
|
return {
|
|
321
409
|
totalFiles,
|
|
322
410
|
totalLines,
|
|
323
411
|
fileTypes,
|
|
324
|
-
largestFiles: largestFiles.slice(0, 10)
|
|
412
|
+
largestFiles: largestFiles.slice(0, 10),
|
|
413
|
+
skippedFiles
|
|
325
414
|
};
|
|
326
415
|
}
|
|
327
416
|
async function analyzeArchitecture(projectPath, keyFiles) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mcp-probe-kit",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.8",
|
|
4
4
|
"description": "Cursor Development Enhancement Toolkit - MCP Server with 23 practical tools for code quality, development efficiency, and project management",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "build/index.js",
|