code-auditor-mcp 2.2.2 → 2.6.1
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/dist/auditRunner.d.ts +1 -1
- package/dist/auditRunner.d.ts.map +1 -1
- package/dist/auditRunner.js +97 -46
- package/dist/auditRunner.js.map +1 -1
- package/dist/codeIndexDb.d.ts.map +1 -1
- package/dist/codeIndexDb.js +2 -0
- package/dist/codeIndexDb.js.map +1 -1
- package/dist/config/configLoader.d.ts +1 -1
- package/dist/config/configLoader.d.ts.map +1 -1
- package/dist/mcp-standalone.js +177 -138
- package/dist/mcp-standalone.js.map +1 -1
- package/dist/mcp-tools/workflowGuide.d.ts.map +1 -1
- package/dist/mcp-tools/workflowGuide.js +79 -45
- package/dist/mcp-tools/workflowGuide.js.map +1 -1
- package/dist/mcp.js +185 -209
- package/dist/mcp.js.map +1 -1
- package/dist/mcpAuditJobs.d.ts +28 -0
- package/dist/mcpAuditJobs.d.ts.map +1 -0
- package/dist/mcpAuditJobs.js +852 -0
- package/dist/mcpAuditJobs.js.map +1 -0
- package/dist/mcpDiagnostics.d.ts +4 -0
- package/dist/mcpDiagnostics.d.ts.map +1 -1
- package/dist/mcpDiagnostics.js +12 -1
- package/dist/mcpDiagnostics.js.map +1 -1
- package/dist/scripts/benchmarkWorkers.d.ts +2 -0
- package/dist/scripts/benchmarkWorkers.d.ts.map +1 -0
- package/dist/scripts/benchmarkWorkers.js +64 -0
- package/dist/scripts/benchmarkWorkers.js.map +1 -0
- package/dist/services/auditJobService.d.ts +28 -0
- package/dist/services/auditJobService.d.ts.map +1 -0
- package/dist/services/auditJobService.js +36 -0
- package/dist/services/auditJobService.js.map +1 -0
- package/dist/types.d.ts +27 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +21 -0
- package/dist/types.js.map +1 -1
- package/dist/workers/auditWorker.d.ts +2 -0
- package/dist/workers/auditWorker.d.ts.map +1 -0
- package/dist/workers/auditWorker.js +122 -0
- package/dist/workers/auditWorker.js.map +1 -0
- package/dist/workers/auditWorkerProtocol.d.ts +85 -0
- package/dist/workers/auditWorkerProtocol.d.ts.map +1 -0
- package/dist/workers/auditWorkerProtocol.js +32 -0
- package/dist/workers/auditWorkerProtocol.js.map +1 -0
- package/package.json +3 -2
package/dist/mcp.js
CHANGED
|
@@ -11,11 +11,12 @@ import { CodeMapGenerator } from './services/CodeMapGenerator.js';
|
|
|
11
11
|
import { analyzeDocumentation } from './analyzers/documentationAnalyzer.js';
|
|
12
12
|
import { ConfigGeneratorFactory } from './generators/ConfigGeneratorFactory.js';
|
|
13
13
|
import { DEFAULT_SERVER_URL, IS_DEV_MODE, PACKAGE_VERSION } from './constants.js';
|
|
14
|
+
import { getAuditJobStatus, getAuditResultsPage, startAuditJob } from './mcpAuditJobs.js';
|
|
14
15
|
import path from 'node:path';
|
|
15
16
|
import fs from 'node:fs/promises';
|
|
16
17
|
import { createWriteStream } from 'node:fs';
|
|
17
18
|
import { CodeIndexDB } from './codeIndexDB.js';
|
|
18
|
-
import { logMcpDebug, logMcpInfo, mcpDebugStderr } from './mcpDiagnostics.js';
|
|
19
|
+
import { logMcpDebug, logMcpInfo, mcpDebugStderr, mcpTraceStderr } from './mcpDiagnostics.js';
|
|
19
20
|
import { assertAuditPathExists, formatMcpToolErrorPayload } from './mcpToolErrors.js';
|
|
20
21
|
// Set up file logging (only in development mode)
|
|
21
22
|
let logStream = null;
|
|
@@ -48,27 +49,59 @@ const tools = [
|
|
|
48
49
|
// Core Audit Tools
|
|
49
50
|
{
|
|
50
51
|
name: 'audit',
|
|
51
|
-
description: '
|
|
52
|
+
description: 'Fetch paginated results for a completed audit by resultId (or auditId alias). This tool never starts a new audit.',
|
|
53
|
+
parameters: [
|
|
54
|
+
{
|
|
55
|
+
name: 'limit',
|
|
56
|
+
type: 'number',
|
|
57
|
+
required: false,
|
|
58
|
+
description: 'Maximum number of violations to return per page (default: 50, max: 100)',
|
|
59
|
+
default: 50,
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
name: 'offset',
|
|
63
|
+
type: 'number',
|
|
64
|
+
required: false,
|
|
65
|
+
description: 'Violation offset for pagination (default: 0).',
|
|
66
|
+
default: 0,
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
name: 'resultId',
|
|
70
|
+
type: 'string',
|
|
71
|
+
required: false,
|
|
72
|
+
description: 'Result ID returned by audit_status when the background audit job completes.',
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
name: 'auditId',
|
|
76
|
+
type: 'string',
|
|
77
|
+
required: false,
|
|
78
|
+
description: 'Backward-compatible alias for resultId.',
|
|
79
|
+
},
|
|
80
|
+
],
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
name: 'start_audit',
|
|
84
|
+
description: 'Start a background audit job. Returns immediately with a jobId. Poll audit_status until completed, then fetch pages with audit or audit_results.',
|
|
52
85
|
parameters: [
|
|
53
86
|
{
|
|
54
87
|
name: 'path',
|
|
55
88
|
type: 'string',
|
|
56
89
|
required: false,
|
|
57
|
-
description: '
|
|
90
|
+
description: 'File or directory path to audit (defaults to current directory).',
|
|
58
91
|
default: process.cwd(),
|
|
59
92
|
},
|
|
60
93
|
{
|
|
61
94
|
name: 'analyzers',
|
|
62
95
|
type: 'array',
|
|
63
96
|
required: false,
|
|
64
|
-
description: '
|
|
97
|
+
description: 'Analyzers to run (default: solid, dry, documentation, react, data-access).',
|
|
65
98
|
default: ['solid', 'dry', 'documentation', 'react', 'data-access'],
|
|
66
99
|
},
|
|
67
100
|
{
|
|
68
101
|
name: 'minSeverity',
|
|
69
102
|
type: 'string',
|
|
70
103
|
required: false,
|
|
71
|
-
description: 'Minimum severity level to report',
|
|
104
|
+
description: 'Minimum severity level to report.',
|
|
72
105
|
default: 'warning',
|
|
73
106
|
enum: ['info', 'warning', 'critical'],
|
|
74
107
|
},
|
|
@@ -76,48 +109,133 @@ const tools = [
|
|
|
76
109
|
name: 'indexFunctions',
|
|
77
110
|
type: 'boolean',
|
|
78
111
|
required: false,
|
|
79
|
-
description: '
|
|
112
|
+
description: 'Index functions during audit (default: true).',
|
|
80
113
|
default: true,
|
|
81
114
|
},
|
|
82
115
|
{
|
|
83
116
|
name: 'analyzerConfigs',
|
|
84
117
|
type: 'object',
|
|
85
118
|
required: false,
|
|
86
|
-
description: 'Analyzer-specific configuration overrides
|
|
119
|
+
description: 'Analyzer-specific configuration overrides.',
|
|
87
120
|
},
|
|
88
121
|
{
|
|
89
|
-
name: '
|
|
90
|
-
type: '
|
|
122
|
+
name: 'analyzerConcurrency',
|
|
123
|
+
type: 'number',
|
|
91
124
|
required: false,
|
|
92
|
-
description: '
|
|
93
|
-
default:
|
|
125
|
+
description: 'Max analyzers to run in parallel (default: 1).',
|
|
126
|
+
default: 1,
|
|
94
127
|
},
|
|
95
128
|
{
|
|
96
|
-
name: '
|
|
129
|
+
name: 'partitionStrategy',
|
|
130
|
+
type: 'string',
|
|
131
|
+
required: false,
|
|
132
|
+
description: 'Partition mode: none | auto | top-level. auto shards when large source trees are detected.',
|
|
133
|
+
default: 'auto',
|
|
134
|
+
enum: ['none', 'auto', 'top-level'],
|
|
135
|
+
},
|
|
136
|
+
{
|
|
137
|
+
name: 'maxPartitions',
|
|
97
138
|
type: 'number',
|
|
98
139
|
required: false,
|
|
99
|
-
description: 'Maximum number of
|
|
100
|
-
default:
|
|
140
|
+
description: 'Maximum number of folder partitions for sharded audits (default: 4).',
|
|
141
|
+
default: 4,
|
|
101
142
|
},
|
|
102
143
|
{
|
|
103
|
-
name: '
|
|
144
|
+
name: 'partitionThresholdFiles',
|
|
104
145
|
type: 'number',
|
|
105
146
|
required: false,
|
|
106
|
-
description: '
|
|
107
|
-
default:
|
|
147
|
+
description: 'Minimum discovered files before auto partitioning is enabled (default: 250).',
|
|
148
|
+
default: 250,
|
|
108
149
|
},
|
|
109
150
|
{
|
|
110
|
-
name: '
|
|
111
|
-
type: '
|
|
151
|
+
name: 'workerCount',
|
|
152
|
+
type: 'number',
|
|
153
|
+
required: false,
|
|
154
|
+
description: 'Number of worker processes for shard execution (default: min(4, CPU-1)).',
|
|
155
|
+
},
|
|
156
|
+
{
|
|
157
|
+
name: 'maxRetries',
|
|
158
|
+
type: 'number',
|
|
159
|
+
required: false,
|
|
160
|
+
description: 'Retry attempts per shard for retryable failures (default: 1).',
|
|
161
|
+
default: 1,
|
|
162
|
+
},
|
|
163
|
+
{
|
|
164
|
+
name: 'shardTimeoutMs',
|
|
165
|
+
type: 'number',
|
|
112
166
|
required: false,
|
|
113
|
-
description: '
|
|
167
|
+
description: 'Per-shard timeout in milliseconds (default: 180000).',
|
|
168
|
+
default: 180000,
|
|
114
169
|
},
|
|
115
170
|
{
|
|
116
|
-
name: '
|
|
171
|
+
name: 'retryBackoffMs',
|
|
172
|
+
type: 'number',
|
|
173
|
+
required: false,
|
|
174
|
+
description: 'Base retry backoff in milliseconds (default: 500).',
|
|
175
|
+
default: 500,
|
|
176
|
+
},
|
|
177
|
+
{
|
|
178
|
+
name: 'jobTimeoutMs',
|
|
179
|
+
type: 'number',
|
|
180
|
+
required: false,
|
|
181
|
+
description: 'Maximum wall time for the entire audit job (default 30m, env CODE_AUDITOR_JOB_TIMEOUT_MS, cap 4h). Aborts workers cooperatively then tears down.',
|
|
182
|
+
},
|
|
183
|
+
{
|
|
184
|
+
name: 'maxFilesPerRun',
|
|
185
|
+
type: 'number',
|
|
186
|
+
required: false,
|
|
187
|
+
description: 'Per worker chunk: if more files match than this, the worker finishes one chunk and the parent queues the rest on another worker (optional).',
|
|
188
|
+
},
|
|
189
|
+
{
|
|
190
|
+
name: 'shardSoftBudgetMs',
|
|
191
|
+
type: 'number',
|
|
192
|
+
required: false,
|
|
193
|
+
description: 'Per worker soft wall-clock budget; aborts in-process analysis cooperatively via AbortSignal so the parent can assign the next chunk to a fresh worker.',
|
|
194
|
+
},
|
|
195
|
+
{
|
|
196
|
+
name: 'generateCodeMap',
|
|
117
197
|
type: 'boolean',
|
|
118
198
|
required: false,
|
|
119
|
-
description: '
|
|
120
|
-
default:
|
|
199
|
+
description: 'Generate code map artifacts during audit (default: false).',
|
|
200
|
+
default: false,
|
|
201
|
+
},
|
|
202
|
+
],
|
|
203
|
+
},
|
|
204
|
+
{
|
|
205
|
+
name: 'audit_status',
|
|
206
|
+
description: 'Get current status for a previously started background audit job. Returns resultId when completed.',
|
|
207
|
+
parameters: [
|
|
208
|
+
{
|
|
209
|
+
name: 'jobId',
|
|
210
|
+
type: 'string',
|
|
211
|
+
required: true,
|
|
212
|
+
description: 'Job ID returned by start_audit.',
|
|
213
|
+
},
|
|
214
|
+
],
|
|
215
|
+
},
|
|
216
|
+
{
|
|
217
|
+
name: 'audit_results',
|
|
218
|
+
description: 'Fetch paginated violations for a completed audit result by resultId.',
|
|
219
|
+
parameters: [
|
|
220
|
+
{
|
|
221
|
+
name: 'resultId',
|
|
222
|
+
type: 'string',
|
|
223
|
+
required: true,
|
|
224
|
+
description: 'Result ID returned by audit_status when status is completed.',
|
|
225
|
+
},
|
|
226
|
+
{
|
|
227
|
+
name: 'limit',
|
|
228
|
+
type: 'number',
|
|
229
|
+
required: false,
|
|
230
|
+
description: 'Maximum number of violations to return per page (default: 50, max: 100).',
|
|
231
|
+
default: 50,
|
|
232
|
+
},
|
|
233
|
+
{
|
|
234
|
+
name: 'offset',
|
|
235
|
+
type: 'number',
|
|
236
|
+
required: false,
|
|
237
|
+
description: 'Violation offset for pagination (default: 0).',
|
|
238
|
+
default: 0,
|
|
121
239
|
},
|
|
122
240
|
],
|
|
123
241
|
},
|
|
@@ -498,7 +616,7 @@ async function startMcpServer() {
|
|
|
498
616
|
console.error(chalk.red('[ERROR]'), 'Error stack:', error.stack);
|
|
499
617
|
};
|
|
500
618
|
server.setRequestHandler(ListToolsRequestSchema, async (request) => {
|
|
501
|
-
|
|
619
|
+
mcpTraceStderr(chalk.blue('[DEBUG]'), 'ListTools', JSON.stringify(request, null, 2));
|
|
502
620
|
const response = {
|
|
503
621
|
tools: tools.map(tool => ({
|
|
504
622
|
name: tool.name,
|
|
@@ -518,11 +636,11 @@ async function startMcpServer() {
|
|
|
518
636
|
},
|
|
519
637
|
})),
|
|
520
638
|
};
|
|
521
|
-
|
|
639
|
+
mcpTraceStderr(chalk.blue('[DEBUG]'), `ListTools → ${response.tools.length} tools`);
|
|
522
640
|
return response;
|
|
523
641
|
});
|
|
524
642
|
server.setRequestHandler(InitializeRequestSchema, async (request) => {
|
|
525
|
-
|
|
643
|
+
mcpTraceStderr(chalk.blue('[DEBUG]'), 'initialize', JSON.stringify(request, null, 2));
|
|
526
644
|
const response = {
|
|
527
645
|
protocolVersion: '2024-11-05',
|
|
528
646
|
capabilities: {
|
|
@@ -533,192 +651,46 @@ async function startMcpServer() {
|
|
|
533
651
|
version: PACKAGE_VERSION,
|
|
534
652
|
},
|
|
535
653
|
};
|
|
536
|
-
|
|
654
|
+
mcpTraceStderr(chalk.blue('[DEBUG]'), 'initialize response', JSON.stringify(response, null, 2));
|
|
537
655
|
return response;
|
|
538
656
|
});
|
|
539
657
|
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
540
|
-
|
|
658
|
+
mcpTraceStderr(chalk.blue('[DEBUG]'), 'CallTool raw', JSON.stringify(request, null, 2));
|
|
541
659
|
const { name, arguments: args } = request.params;
|
|
542
|
-
|
|
660
|
+
mcpTraceStderr(chalk.blue('[DEBUG]'), `CallTool ${name}`, JSON.stringify(args, null, 2));
|
|
543
661
|
const toolStartedAt = Date.now();
|
|
544
662
|
try {
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
663
|
+
if (name !== 'audit_status') {
|
|
664
|
+
logMcpDebug('tool', `call ${name}`, {
|
|
665
|
+
argKeys: args && typeof args === 'object' ? Object.keys(args) : [],
|
|
666
|
+
pathArg: args?.path,
|
|
667
|
+
cwd: process.cwd()
|
|
668
|
+
});
|
|
669
|
+
}
|
|
550
670
|
let result;
|
|
551
671
|
switch (name) {
|
|
552
|
-
case '
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
if (providedAuditId) {
|
|
565
|
-
const cachedResult = await db.getAuditResults(providedAuditId);
|
|
566
|
-
if (cachedResult) {
|
|
567
|
-
auditResult = cachedResult;
|
|
568
|
-
mcpDebugStderr(chalk.blue('[INFO]'), `Using cached audit results: ${providedAuditId}`);
|
|
569
|
-
}
|
|
570
|
-
else {
|
|
571
|
-
mcpDebugStderr(chalk.yellow('[WARN]'), `Cached audit not found: ${providedAuditId}, running new audit`);
|
|
572
|
-
}
|
|
573
|
-
}
|
|
574
|
-
let isFile = false;
|
|
575
|
-
if (!auditResult) {
|
|
576
|
-
const pathCheck = await assertAuditPathExists(auditPath);
|
|
577
|
-
isFile = pathCheck.isFile;
|
|
578
|
-
const storedConfigs = await db.getAllAnalyzerConfigs(auditPath);
|
|
579
|
-
const analyzerConfigs = {
|
|
580
|
-
...storedConfigs,
|
|
581
|
-
...(args.analyzerConfigs || {})
|
|
582
|
-
};
|
|
583
|
-
const options = {
|
|
584
|
-
projectRoot: isFile ? path.dirname(auditPath) : auditPath,
|
|
585
|
-
enabledAnalyzers: args.analyzers || ['solid', 'dry', 'documentation', 'react', 'data-access'],
|
|
586
|
-
minSeverity: (args.minSeverity || 'warning'),
|
|
587
|
-
verbose: false,
|
|
588
|
-
indexFunctions,
|
|
589
|
-
...(isFile && { includePaths: [auditPath] }),
|
|
590
|
-
...(Object.keys(analyzerConfigs).length > 0 && { analyzerConfigs }),
|
|
591
|
-
progressCallback: (p) => {
|
|
592
|
-
if (p.phase === 'function-indexing' &&
|
|
593
|
-
typeof p.current === 'number' &&
|
|
594
|
-
typeof p.total === 'number' &&
|
|
595
|
-
p.total > 0 &&
|
|
596
|
-
p.current % 50 !== 0 &&
|
|
597
|
-
p.current !== p.total) {
|
|
598
|
-
return;
|
|
599
|
-
}
|
|
600
|
-
logMcpDebug('audit', p.message ?? p.phase ?? 'progress', {
|
|
601
|
-
phase: p.phase,
|
|
602
|
-
analyzer: p.analyzer,
|
|
603
|
-
current: p.current,
|
|
604
|
-
total: p.total
|
|
605
|
-
});
|
|
606
|
-
}
|
|
607
|
-
};
|
|
608
|
-
mcpDebugStderr(chalk.blue('[DEBUG]'), 'audit runner options', JSON.stringify(options, null, 2));
|
|
609
|
-
const runner = createAuditRunner(options);
|
|
610
|
-
auditResult = await runner.run();
|
|
611
|
-
mcpDebugStderr(chalk.blue('[DEBUG]'), 'audit summary', auditResult.summary);
|
|
612
|
-
const projectRootForStore = isFile ? path.dirname(auditPath) : auditPath;
|
|
613
|
-
if (useCache) {
|
|
614
|
-
auditId = await db.storeAuditResults(auditResult, projectRootForStore);
|
|
615
|
-
mcpDebugStderr(chalk.blue('[INFO]'), `Stored audit results with ID: ${auditId}`);
|
|
616
|
-
}
|
|
617
|
-
}
|
|
618
|
-
const mapBasePath = auditResult.projectPath != null
|
|
619
|
-
? path.resolve(String(auditResult.projectPath))
|
|
620
|
-
: auditPath;
|
|
621
|
-
// Handle function indexing if enabled and functions were collected
|
|
622
|
-
let indexingResult = null;
|
|
623
|
-
if (indexFunctions && auditResult.metadata.fileToFunctionsMap) {
|
|
624
|
-
try {
|
|
625
|
-
const syncStats = { added: 0, updated: 0, removed: 0 };
|
|
626
|
-
// Sync each file's functions to handle additions, updates, and removals
|
|
627
|
-
for (const [filePath, functions] of Object.entries(auditResult.metadata.fileToFunctionsMap)) {
|
|
628
|
-
const fileStats = await syncFileIndex(filePath, functions);
|
|
629
|
-
syncStats.added += fileStats.added;
|
|
630
|
-
syncStats.updated += fileStats.updated;
|
|
631
|
-
syncStats.removed += fileStats.removed;
|
|
632
|
-
}
|
|
633
|
-
indexingResult = {
|
|
634
|
-
success: true,
|
|
635
|
-
registered: syncStats.added + syncStats.updated,
|
|
636
|
-
failed: 0,
|
|
637
|
-
syncStats
|
|
638
|
-
};
|
|
639
|
-
mcpDebugStderr(chalk.blue('[INFO]'), `Synced functions: ${syncStats.added} added, ${syncStats.updated} updated, ${syncStats.removed} removed`);
|
|
640
|
-
}
|
|
641
|
-
catch (error) {
|
|
642
|
-
console.error(chalk.yellow('[WARN]'), 'Failed to sync functions:', error);
|
|
643
|
-
}
|
|
644
|
-
}
|
|
645
|
-
// Generate code map if requested and functions were indexed
|
|
646
|
-
let codeMapResult = null;
|
|
647
|
-
if (generateCodeMap && indexingResult && indexingResult.success) {
|
|
648
|
-
try {
|
|
649
|
-
const mapGenerator = new CodeMapGenerator();
|
|
650
|
-
const mapOptions = {
|
|
651
|
-
includeComplexity: true,
|
|
652
|
-
includeDocumentation: true,
|
|
653
|
-
includeDependencies: true,
|
|
654
|
-
includeUsage: false,
|
|
655
|
-
groupByDirectory: true,
|
|
656
|
-
maxDepth: 10,
|
|
657
|
-
showUnusedImports: true,
|
|
658
|
-
minComplexity: 7,
|
|
659
|
-
};
|
|
660
|
-
// Generate documentation metrics
|
|
661
|
-
let documentation = undefined;
|
|
662
|
-
try {
|
|
663
|
-
// Use existing file discovery from audit result
|
|
664
|
-
const files = Object.keys(auditResult.metadata.fileToFunctionsMap || {});
|
|
665
|
-
if (files.length > 0) {
|
|
666
|
-
const docResult = await analyzeDocumentation(files);
|
|
667
|
-
documentation = docResult.metrics;
|
|
668
|
-
}
|
|
669
|
-
}
|
|
670
|
-
catch (docError) {
|
|
671
|
-
console.error(chalk.yellow('[WARN]'), 'Failed to analyze documentation:', docError);
|
|
672
|
-
}
|
|
673
|
-
// Use paginated code map generation
|
|
674
|
-
const paginatedResult = await mapGenerator.generatePaginatedCodeMap(mapBasePath, {
|
|
675
|
-
...mapOptions,
|
|
676
|
-
includeDocumentation: !!documentation
|
|
677
|
-
});
|
|
678
|
-
codeMapResult = {
|
|
679
|
-
success: true,
|
|
680
|
-
mapId: paginatedResult.mapId,
|
|
681
|
-
summary: paginatedResult.summary,
|
|
682
|
-
quickPreview: paginatedResult.quickPreview,
|
|
683
|
-
sections: paginatedResult.summary.sectionsAvailable,
|
|
684
|
-
documentationCoverage: documentation?.coverageScore
|
|
685
|
-
};
|
|
686
|
-
mcpDebugStderr(chalk.blue('[INFO]'), `Generated paginated code map: ${paginatedResult.summary.stats.totalFiles} files, ${paginatedResult.summary.totalSections} sections`);
|
|
687
|
-
}
|
|
688
|
-
catch (error) {
|
|
689
|
-
console.error(chalk.yellow('[WARN]'), 'Failed to generate code map:', error);
|
|
690
|
-
codeMapResult = {
|
|
691
|
-
success: false,
|
|
692
|
-
error: error instanceof Error ? error.message : 'Failed to generate code map'
|
|
693
|
-
};
|
|
694
|
-
}
|
|
672
|
+
case 'start_audit': {
|
|
673
|
+
result = await startAuditJob(args, {
|
|
674
|
+
defaultAnalyzers: ['solid', 'dry', 'documentation', 'react', 'data-access'],
|
|
675
|
+
defaultMinSeverity: 'warning',
|
|
676
|
+
defaultGenerateCodeMap: false,
|
|
677
|
+
});
|
|
678
|
+
break;
|
|
679
|
+
}
|
|
680
|
+
case 'audit_status': {
|
|
681
|
+
const jobId = args.jobId;
|
|
682
|
+
if (!jobId) {
|
|
683
|
+
throw new Error('audit_status requires jobId');
|
|
695
684
|
}
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
filesAnalyzed: auditResult.metadata.filesAnalyzed,
|
|
706
|
-
executionTime: auditResult.metadata.auditDuration,
|
|
707
|
-
healthScore: calculateHealthScore(auditResult),
|
|
708
|
-
},
|
|
709
|
-
violations: paginatedViolations,
|
|
710
|
-
pagination: {
|
|
711
|
-
total: allViolations.length,
|
|
712
|
-
limit,
|
|
713
|
-
offset,
|
|
714
|
-
hasMore: offset + limit < allViolations.length,
|
|
715
|
-
nextOffset: offset + limit < allViolations.length ? offset + limit : null,
|
|
716
|
-
auditId: auditId ?? null,
|
|
717
|
-
},
|
|
718
|
-
recommendations: auditResult.recommendations,
|
|
719
|
-
...(indexingResult && { functionIndexing: indexingResult }),
|
|
720
|
-
...(codeMapResult && { codeMap: codeMapResult }),
|
|
721
|
-
};
|
|
685
|
+
result = getAuditJobStatus(jobId);
|
|
686
|
+
break;
|
|
687
|
+
}
|
|
688
|
+
case 'audit_results': {
|
|
689
|
+
result = await getAuditResultsPage(args);
|
|
690
|
+
break;
|
|
691
|
+
}
|
|
692
|
+
case 'audit': {
|
|
693
|
+
result = await getAuditResultsPage(args);
|
|
722
694
|
break;
|
|
723
695
|
}
|
|
724
696
|
case 'audit_health': {
|
|
@@ -1202,16 +1174,18 @@ async function startMcpServer() {
|
|
|
1202
1174
|
},
|
|
1203
1175
|
],
|
|
1204
1176
|
};
|
|
1205
|
-
|
|
1177
|
+
mcpTraceStderr(chalk.blue('[DEBUG]'), `Tool ${name} ok`, JSON.stringify(response, null, 2).substring(0, 500) + '...');
|
|
1206
1178
|
return response;
|
|
1207
1179
|
}
|
|
1208
1180
|
catch (error) {
|
|
1209
1181
|
console.error(chalk.red('[ERROR]'), `Tool ${name} execution failed:`, error);
|
|
1210
1182
|
console.error(chalk.red('[ERROR]'), 'Error stack:', error instanceof Error ? error.stack : 'No stack trace');
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1183
|
+
if (name !== 'audit_status') {
|
|
1184
|
+
logMcpDebug('tool', `call ${name} failed`, {
|
|
1185
|
+
ms: Date.now() - toolStartedAt,
|
|
1186
|
+
error: error instanceof Error ? error.message : String(error)
|
|
1187
|
+
});
|
|
1188
|
+
}
|
|
1215
1189
|
return {
|
|
1216
1190
|
content: [
|
|
1217
1191
|
{
|
|
@@ -1223,7 +1197,9 @@ async function startMcpServer() {
|
|
|
1223
1197
|
};
|
|
1224
1198
|
}
|
|
1225
1199
|
finally {
|
|
1226
|
-
|
|
1200
|
+
if (name !== 'audit_status') {
|
|
1201
|
+
logMcpDebug('tool', `call ${name} finished`, { ms: Date.now() - toolStartedAt });
|
|
1202
|
+
}
|
|
1227
1203
|
}
|
|
1228
1204
|
});
|
|
1229
1205
|
const transport = new StdioServerTransport();
|