code-auditor-mcp 2.2.2 → 2.6.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.
Files changed (42) hide show
  1. package/dist/auditRunner.d.ts +1 -1
  2. package/dist/auditRunner.d.ts.map +1 -1
  3. package/dist/auditRunner.js +97 -46
  4. package/dist/auditRunner.js.map +1 -1
  5. package/dist/config/configLoader.d.ts +1 -1
  6. package/dist/config/configLoader.d.ts.map +1 -1
  7. package/dist/mcp-standalone.js +177 -138
  8. package/dist/mcp-standalone.js.map +1 -1
  9. package/dist/mcp-tools/workflowGuide.d.ts.map +1 -1
  10. package/dist/mcp-tools/workflowGuide.js +79 -45
  11. package/dist/mcp-tools/workflowGuide.js.map +1 -1
  12. package/dist/mcp.js +185 -209
  13. package/dist/mcp.js.map +1 -1
  14. package/dist/mcpAuditJobs.d.ts +28 -0
  15. package/dist/mcpAuditJobs.d.ts.map +1 -0
  16. package/dist/mcpAuditJobs.js +852 -0
  17. package/dist/mcpAuditJobs.js.map +1 -0
  18. package/dist/mcpDiagnostics.d.ts +4 -0
  19. package/dist/mcpDiagnostics.d.ts.map +1 -1
  20. package/dist/mcpDiagnostics.js +12 -1
  21. package/dist/mcpDiagnostics.js.map +1 -1
  22. package/dist/scripts/benchmarkWorkers.d.ts +2 -0
  23. package/dist/scripts/benchmarkWorkers.d.ts.map +1 -0
  24. package/dist/scripts/benchmarkWorkers.js +64 -0
  25. package/dist/scripts/benchmarkWorkers.js.map +1 -0
  26. package/dist/services/auditJobService.d.ts +28 -0
  27. package/dist/services/auditJobService.d.ts.map +1 -0
  28. package/dist/services/auditJobService.js +36 -0
  29. package/dist/services/auditJobService.js.map +1 -0
  30. package/dist/types.d.ts +27 -0
  31. package/dist/types.d.ts.map +1 -1
  32. package/dist/types.js +21 -0
  33. package/dist/types.js.map +1 -1
  34. package/dist/workers/auditWorker.d.ts +2 -0
  35. package/dist/workers/auditWorker.d.ts.map +1 -0
  36. package/dist/workers/auditWorker.js +122 -0
  37. package/dist/workers/auditWorker.js.map +1 -0
  38. package/dist/workers/auditWorkerProtocol.d.ts +85 -0
  39. package/dist/workers/auditWorkerProtocol.d.ts.map +1 -0
  40. package/dist/workers/auditWorkerProtocol.js +32 -0
  41. package/dist/workers/auditWorkerProtocol.js.map +1 -0
  42. 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: 'Run a comprehensive code audit on files or directories, including React component analysis. Responses include pagination (total, hasMore, nextOffset, auditId). After a full run with useCache true, fetch more violations with the same auditId plus offset/limit only — no full re-audit.',
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: 'The file or directory path to audit (defaults to current directory)',
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: 'List of analyzers to run (solid, dry, documentation, react, data-access)',
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: 'Automatically index functions during audit',
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 (e.g., SOLID thresholds, DRY settings)',
119
+ description: 'Analyzer-specific configuration overrides.',
87
120
  },
88
121
  {
89
- name: 'generateCodeMap',
90
- type: 'boolean',
122
+ name: 'analyzerConcurrency',
123
+ type: 'number',
91
124
  required: false,
92
- description: 'Generate and return a human-readable code map as part of the audit results',
93
- default: true,
125
+ description: 'Max analyzers to run in parallel (default: 1).',
126
+ default: 1,
94
127
  },
95
128
  {
96
- name: 'limit',
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 violations to return per page (default: 50, max: 100)',
100
- default: 50,
140
+ description: 'Maximum number of folder partitions for sharded audits (default: 4).',
141
+ default: 4,
101
142
  },
102
143
  {
103
- name: 'offset',
144
+ name: 'partitionThresholdFiles',
104
145
  type: 'number',
105
146
  required: false,
106
- description: 'Violation offset for pagination (default: 0). Use with auditId from a prior response to read cached pages only.',
107
- default: 0,
147
+ description: 'Minimum discovered files before auto partitioning is enabled (default: 250).',
148
+ default: 250,
108
149
  },
109
150
  {
110
- name: 'auditId',
111
- type: 'string',
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: 'Return violations from a cached audit by ID (from pagination.auditId). When set and found, no full audit is run; use offset/limit for pages.',
167
+ description: 'Per-shard timeout in milliseconds (default: 180000).',
168
+ default: 180000,
114
169
  },
115
170
  {
116
- name: 'useCache',
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: 'Persist full results for pagination (default: true). If false, pagination.auditId may be null.',
120
- default: true,
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
- mcpDebugStderr(chalk.blue('[DEBUG]'), 'ListTools', JSON.stringify(request, null, 2));
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
- mcpDebugStderr(chalk.blue('[DEBUG]'), `ListTools → ${response.tools.length} tools`);
639
+ mcpTraceStderr(chalk.blue('[DEBUG]'), `ListTools → ${response.tools.length} tools`);
522
640
  return response;
523
641
  });
524
642
  server.setRequestHandler(InitializeRequestSchema, async (request) => {
525
- mcpDebugStderr(chalk.blue('[DEBUG]'), 'initialize', JSON.stringify(request, null, 2));
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
- mcpDebugStderr(chalk.blue('[DEBUG]'), 'initialize response', JSON.stringify(response, null, 2));
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
- mcpDebugStderr(chalk.blue('[DEBUG]'), 'CallTool raw', JSON.stringify(request, null, 2));
658
+ mcpTraceStderr(chalk.blue('[DEBUG]'), 'CallTool raw', JSON.stringify(request, null, 2));
541
659
  const { name, arguments: args } = request.params;
542
- mcpDebugStderr(chalk.blue('[DEBUG]'), `CallTool ${name}`, JSON.stringify(args, null, 2));
660
+ mcpTraceStderr(chalk.blue('[DEBUG]'), `CallTool ${name}`, JSON.stringify(args, null, 2));
543
661
  const toolStartedAt = Date.now();
544
662
  try {
545
- logMcpDebug('tool', `call ${name}`, {
546
- argKeys: args && typeof args === 'object' ? Object.keys(args) : [],
547
- pathArg: args?.path,
548
- cwd: process.cwd()
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 'audit': {
553
- const auditPath = path.resolve(args.path || process.cwd());
554
- const indexFunctions = args.indexFunctions !== false; // Default true
555
- const generateCodeMap = args.generateCodeMap || false;
556
- const limit = Math.min(Math.max(0, Number(args.limit)) || 50, 100);
557
- const offset = Math.max(0, Number(args.offset) || 0);
558
- const useCache = args.useCache !== false;
559
- const providedAuditId = args.auditId;
560
- let auditResult;
561
- let auditId = providedAuditId;
562
- const db = CodeIndexDB.getInstance();
563
- await db.initialize();
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
- const allViolations = auditResult.violations || getAllViolations(auditResult);
697
- const paginatedViolations = allViolations.slice(offset, offset + limit);
698
- // Format for MCP
699
- result = {
700
- summary: {
701
- totalViolations: auditResult.summary.totalViolations,
702
- criticalIssues: auditResult.summary.criticalIssues,
703
- warnings: auditResult.summary.warnings,
704
- suggestions: auditResult.summary.suggestions,
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
- mcpDebugStderr(chalk.blue('[DEBUG]'), `Tool ${name} ok`, JSON.stringify(response, null, 2).substring(0, 500) + '...');
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
- logMcpDebug('tool', `call ${name} failed`, {
1212
- ms: Date.now() - toolStartedAt,
1213
- error: error instanceof Error ? error.message : String(error)
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
- logMcpDebug('tool', `call ${name} finished`, { ms: Date.now() - toolStartedAt });
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();