code-auditor-mcp 2.0.3 → 2.2.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.
Files changed (76) hide show
  1. package/README.md +41 -3
  2. package/dist/applyDataDirEnv.d.ts +2 -0
  3. package/dist/applyDataDirEnv.d.ts.map +1 -0
  4. package/dist/applyDataDirEnv.js +21 -0
  5. package/dist/applyDataDirEnv.js.map +1 -0
  6. package/dist/auditRunner.d.ts.map +1 -1
  7. package/dist/auditRunner.js +48 -13
  8. package/dist/auditRunner.js.map +1 -1
  9. package/dist/codeIndexDB-enhanced.d.ts +2 -3
  10. package/dist/codeIndexDB-enhanced.d.ts.map +1 -1
  11. package/dist/codeIndexDB-enhanced.js +41 -15
  12. package/dist/codeIndexDB-enhanced.js.map +1 -1
  13. package/dist/codeIndexDb.d.ts +30 -1
  14. package/dist/codeIndexDb.d.ts.map +1 -1
  15. package/dist/codeIndexDb.js +114 -15
  16. package/dist/codeIndexDb.js.map +1 -1
  17. package/dist/codeIndexService.d.ts +7 -3
  18. package/dist/codeIndexService.d.ts.map +1 -1
  19. package/dist/codeIndexService.js +14 -22
  20. package/dist/codeIndexService.js.map +1 -1
  21. package/dist/constants.d.ts +2 -0
  22. package/dist/constants.d.ts.map +1 -1
  23. package/dist/constants.js +6 -0
  24. package/dist/constants.js.map +1 -1
  25. package/dist/dataPaths.d.ts +10 -0
  26. package/dist/dataPaths.d.ts.map +1 -0
  27. package/dist/dataPaths.js +19 -0
  28. package/dist/dataPaths.js.map +1 -0
  29. package/dist/mcp-index.d.ts +3 -1
  30. package/dist/mcp-index.d.ts.map +1 -1
  31. package/dist/mcp-index.js +30 -8
  32. package/dist/mcp-index.js.map +1 -1
  33. package/dist/mcp-standalone.d.ts +1 -1
  34. package/dist/mcp-standalone.d.ts.map +1 -1
  35. package/dist/mcp-standalone.js +163 -59
  36. package/dist/mcp-standalone.js.map +1 -1
  37. package/dist/mcp-tools/projectTasks.d.ts +69 -0
  38. package/dist/mcp-tools/projectTasks.d.ts.map +1 -0
  39. package/dist/mcp-tools/projectTasks.js +129 -0
  40. package/dist/mcp-tools/projectTasks.js.map +1 -0
  41. package/dist/mcp-tools-shared.d.ts.map +1 -1
  42. package/dist/mcp-tools-shared.js +3 -3
  43. package/dist/mcp-tools-shared.js.map +1 -1
  44. package/dist/mcp-ui-simple.d.ts.map +1 -1
  45. package/dist/mcp-ui-simple.js +3 -2
  46. package/dist/mcp-ui-simple.js.map +1 -1
  47. package/dist/mcp.js +206 -65
  48. package/dist/mcp.js.map +1 -1
  49. package/dist/mcpAutoIndex.d.ts +2 -0
  50. package/dist/mcpAutoIndex.d.ts.map +1 -0
  51. package/dist/mcpAutoIndex.js +71 -0
  52. package/dist/mcpAutoIndex.js.map +1 -0
  53. package/dist/mcpDiagnostics.d.ts +11 -0
  54. package/dist/mcpDiagnostics.d.ts.map +1 -0
  55. package/dist/mcpDiagnostics.js +54 -0
  56. package/dist/mcpDiagnostics.js.map +1 -0
  57. package/dist/mcpToolErrors.d.ts +21 -0
  58. package/dist/mcpToolErrors.d.ts.map +1 -0
  59. package/dist/mcpToolErrors.js +81 -0
  60. package/dist/mcpToolErrors.js.map +1 -0
  61. package/dist/search/QueryParser.d.ts.map +1 -1
  62. package/dist/search/QueryParser.js +11 -12
  63. package/dist/search/QueryParser.js.map +1 -1
  64. package/dist/services/ProjectTaskRepository.d.ts +20 -0
  65. package/dist/services/ProjectTaskRepository.d.ts.map +1 -0
  66. package/dist/services/ProjectTaskRepository.js +96 -0
  67. package/dist/services/ProjectTaskRepository.js.map +1 -0
  68. package/dist/services/projectTaskHelpers.d.ts +23 -0
  69. package/dist/services/projectTaskHelpers.d.ts.map +1 -0
  70. package/dist/services/projectTaskHelpers.js +232 -0
  71. package/dist/services/projectTaskHelpers.js.map +1 -0
  72. package/dist/types/projectTask.d.ts +64 -0
  73. package/dist/types/projectTask.d.ts.map +1 -0
  74. package/dist/types/projectTask.js +6 -0
  75. package/dist/types/projectTask.js.map +1 -0
  76. package/package.json +34 -27
package/dist/mcp.js CHANGED
@@ -2,24 +2,21 @@
2
2
  // MCP servers use stdio: stdout for protocol messages, stderr for logging
3
3
  // All log messages must go to stderr to avoid interfering with MCP protocol
4
4
  import chalk from 'chalk';
5
- console.error(chalk.blue('[INFO]'), 'Loading modules...');
6
5
  import { Server } from '@modelcontextprotocol/sdk/server/index.js';
7
6
  import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
8
7
  import { CallToolRequestSchema, ListToolsRequestSchema, InitializeRequestSchema } from '@modelcontextprotocol/sdk/types.js';
9
- console.error(chalk.blue('[INFO]'), 'MCP SDK loaded');
10
8
  import { createAuditRunner } from './auditRunner.js';
11
- console.error(chalk.blue('[INFO]'), 'Audit runner loaded');
12
9
  import { searchFunctions, findDefinition, syncFileIndex, getDatabase } from './codeIndexService.js';
13
10
  import { CodeMapGenerator } from './services/CodeMapGenerator.js';
14
11
  import { analyzeDocumentation } from './analyzers/documentationAnalyzer.js';
15
12
  import { ConfigGeneratorFactory } from './generators/ConfigGeneratorFactory.js';
16
- import { DEFAULT_SERVER_URL, IS_DEV_MODE } from './constants.js';
17
- console.error(chalk.blue('[INFO]'), 'Code index service loaded');
13
+ import { DEFAULT_SERVER_URL, IS_DEV_MODE, PACKAGE_VERSION } from './constants.js';
18
14
  import path from 'node:path';
19
15
  import fs from 'node:fs/promises';
20
16
  import { createWriteStream } from 'node:fs';
21
17
  import { CodeIndexDB } from './codeIndexDB.js';
22
- console.error(chalk.blue('[INFO]'), 'All modules loaded successfully');
18
+ import { logMcpDebug, logMcpInfo, mcpDebugStderr } from './mcpDiagnostics.js';
19
+ import { assertAuditPathExists, formatMcpToolErrorPayload } from './mcpToolErrors.js';
23
20
  // Set up file logging (only in development mode)
24
21
  let logStream = null;
25
22
  if (IS_DEV_MODE) {
@@ -27,17 +24,16 @@ if (IS_DEV_MODE) {
27
24
  logStream = createWriteStream(logFilePath, { flags: 'a' });
28
25
  console.error(chalk.blue('[INFO]'), `Development mode: Logging to file: ${logFilePath}`);
29
26
  }
30
- // Save original console methods
31
- const originalConsoleLog = console.log;
27
+ // Save original console.error (log is redirected to stderr; see below)
32
28
  const originalConsoleError = console.error;
33
- // Override console.log (with conditional file logging)
29
+ // Override console.log — MCP uses stdout only for JSON-RPC; log() must never touch stdout.
34
30
  console.log = (...args) => {
35
31
  if (logStream) {
36
32
  const message = args.map(arg => typeof arg === 'object' ? JSON.stringify(arg) : String(arg)).join(' ');
37
33
  const timestamp = new Date().toISOString();
38
34
  logStream.write(`[${timestamp}] [LOG] ${message}\n`);
39
35
  }
40
- originalConsoleLog.apply(console, args);
36
+ originalConsoleError.apply(console, args);
41
37
  };
42
38
  // Override console.error (with conditional file logging)
43
39
  console.error = (...args) => {
@@ -191,13 +187,13 @@ const tools = [
191
187
  },
192
188
  {
193
189
  name: 'sync_index',
194
- description: 'Synchronize, cleanup, or reset the code index',
190
+ description: 'Synchronize, cleanup, or reset analysis-derived data (indexed functions, FlexSearch, cached audits, code maps, schema overlays). Project tasks, analyzer configs, and whitelist entries are preserved on reset.',
195
191
  parameters: [
196
192
  {
197
193
  name: 'mode',
198
194
  type: 'string',
199
195
  required: false,
200
- description: 'Operation mode: sync (update), cleanup (remove stale), or reset (clear all)',
196
+ description: 'sync: update index from files; cleanup: remove index rows for deleted files; reset: clear all analysis-derived data (not tasks/config/whitelist)',
201
197
  default: 'sync',
202
198
  enum: ['sync', 'cleanup', 'reset'],
203
199
  },
@@ -333,32 +329,149 @@ const tools = [
333
329
  },
334
330
  ],
335
331
  },
332
+ {
333
+ name: 'project_tasks',
334
+ description: 'Manage a persistent per-project task queue. Tasks and analyzer configs survive sync_index reset; reset clears function index, cached audits, code maps, and schema overlays (no ghost code references). Use delete to remove a task.',
335
+ parameters: [
336
+ {
337
+ name: 'action',
338
+ type: 'string',
339
+ required: true,
340
+ description: 'list | create | get | update | delete. list/create use projectPath or default to process.cwd(); create also needs title; get/update/delete need taskId; update needs patch object.',
341
+ enum: ['list', 'create', 'get', 'update', 'delete'],
342
+ },
343
+ {
344
+ name: 'projectPath',
345
+ type: 'string',
346
+ required: false,
347
+ description: 'Project root (resolved). Omit to use the MCP server working directory (same default idea as audit path); response includes projectPathDefaulted when omitted.',
348
+ },
349
+ {
350
+ name: 'taskId',
351
+ type: 'string',
352
+ required: false,
353
+ description: 'Stable task id (UUID). Required for get, update, delete.',
354
+ },
355
+ {
356
+ name: 'title',
357
+ type: 'string',
358
+ required: false,
359
+ description: 'Task title. Required for create.',
360
+ },
361
+ {
362
+ name: 'description',
363
+ type: 'string',
364
+ required: false,
365
+ description: 'Longer description / notes.',
366
+ },
367
+ {
368
+ name: 'status',
369
+ type: 'string',
370
+ required: false,
371
+ description: 'pending | in_progress | blocked | done | cancelled. Filter for list; initial status for create; can be set via update patch.',
372
+ enum: ['pending', 'in_progress', 'blocked', 'done', 'cancelled'],
373
+ },
374
+ {
375
+ name: 'priority',
376
+ type: 'string',
377
+ required: false,
378
+ description: 'Optional priority for create/update patch.',
379
+ enum: ['low', 'medium', 'high'],
380
+ },
381
+ {
382
+ name: 'labels',
383
+ type: 'array',
384
+ required: false,
385
+ description: 'String tags (e.g. ["audit","refactor"]).',
386
+ },
387
+ {
388
+ name: 'metadata',
389
+ type: 'object',
390
+ required: false,
391
+ description: 'Arbitrary JSON object: related file paths, links, audit IDs, etc.',
392
+ },
393
+ {
394
+ name: 'parentTaskId',
395
+ type: 'string',
396
+ required: false,
397
+ description: 'Optional parent task for subtasks.',
398
+ },
399
+ {
400
+ name: 'source',
401
+ type: 'string',
402
+ required: false,
403
+ description: 'manual | audit | mcp. Filter for list; provenance for create; can be set via update patch.',
404
+ enum: ['manual', 'audit', 'mcp'],
405
+ },
406
+ {
407
+ name: 'blockedBy',
408
+ type: 'array',
409
+ required: false,
410
+ description: 'Task IDs this item is blocked by (waiting-on).',
411
+ },
412
+ {
413
+ name: 'dueAt',
414
+ type: 'string',
415
+ required: false,
416
+ description: 'ISO 8601 due datetime for create; omit or null in patch to clear.',
417
+ },
418
+ {
419
+ name: 'sortOrder',
420
+ type: 'number',
421
+ required: false,
422
+ description: 'Lower numbers sort first within a project (default 0).',
423
+ },
424
+ {
425
+ name: 'relatedFiles',
426
+ type: 'array',
427
+ required: false,
428
+ description: 'Repo-relative or absolute file paths tied to the task.',
429
+ },
430
+ {
431
+ name: 'relatedSymbols',
432
+ type: 'array',
433
+ required: false,
434
+ description: 'Function, class, or component names for cross-linking.',
435
+ },
436
+ {
437
+ name: 'patch',
438
+ type: 'object',
439
+ required: false,
440
+ description: 'For update: partial fields (title, description, status, priority, labels, metadata, parentTaskId, source, blockedBy, dueAt, sortOrder, relatedFiles, relatedSymbols).',
441
+ },
442
+ {
443
+ name: 'limit',
444
+ type: 'number',
445
+ required: false,
446
+ description: 'Max tasks to return for list (default 500, max 1000).',
447
+ },
448
+ ],
449
+ },
336
450
  ];
337
451
  async function startMcpServer() {
338
- console.error(chalk.blue('[INFO]'), 'Starting Code Auditor MCP Server...');
339
- console.error(chalk.blue('[DEBUG]'), `Process PID: ${process.pid}`);
340
- console.error(chalk.blue('[DEBUG]'), `Node version: ${process.version}`);
341
- console.error(chalk.blue('[DEBUG]'), `Working directory: ${process.cwd()}`);
452
+ logMcpInfo('startup', `code-auditor-mcp ${PACKAGE_VERSION} (stdio)`, {
453
+ pid: process.pid,
454
+ cwd: process.cwd(),
455
+ dataDir: process.env.CODE_AUDITOR_DATA_DIR ?? '(default)',
456
+ debug: process.env.CODE_AUDITOR_DEBUG ?? '0',
457
+ logFile: process.env.CODE_AUDITOR_LOG_FILE ?? '(none)'
458
+ });
459
+ mcpDebugStderr(chalk.blue('[DEBUG]'), `Node ${process.version} · cwd ${process.cwd()}`);
342
460
  const server = new Server({
343
461
  name: 'code-auditor',
462
+ version: PACKAGE_VERSION,
344
463
  }, {
345
464
  capabilities: {
346
465
  tools: {},
347
466
  },
348
467
  });
349
- console.error(chalk.blue('[INFO]'), 'Server instance created');
350
- console.error(chalk.blue('[DEBUG]'), 'Server capabilities:', JSON.stringify({ tools: {} }));
351
468
  // Add error handler
352
469
  server.onerror = (error) => {
353
470
  console.error(chalk.red('[ERROR]'), 'Server error occurred:', error);
354
471
  console.error(chalk.red('[ERROR]'), 'Error stack:', error.stack);
355
472
  };
356
- // Handle tool listing
357
- console.error(chalk.blue('[INFO]'), 'Setting up request handlers...');
358
473
  server.setRequestHandler(ListToolsRequestSchema, async (request) => {
359
- console.error(chalk.blue('[DEBUG]'), 'Received ListTools request');
360
- console.error(chalk.blue('[DEBUG]'), 'Request:', JSON.stringify(request, null, 2));
361
- console.error(chalk.blue('[DEBUG]'), 'Handling ListTools request');
474
+ mcpDebugStderr(chalk.blue('[DEBUG]'), 'ListTools', JSON.stringify(request, null, 2));
362
475
  const response = {
363
476
  tools: tools.map(tool => ({
364
477
  name: tool.name,
@@ -378,15 +491,11 @@ async function startMcpServer() {
378
491
  },
379
492
  })),
380
493
  };
381
- console.error(chalk.blue('[DEBUG]'), `Returning ${response.tools.length} tools`);
382
- console.error(chalk.blue('[DEBUG]'), 'ListTools response:', JSON.stringify(response, null, 2));
494
+ mcpDebugStderr(chalk.blue('[DEBUG]'), `ListTools ${response.tools.length} tools`);
383
495
  return response;
384
496
  });
385
- console.error(chalk.blue('[INFO]'), `Registered ${tools.length} tools`);
386
- // Add handler for initialize request
387
497
  server.setRequestHandler(InitializeRequestSchema, async (request) => {
388
- console.error(chalk.blue('[DEBUG]'), 'Received initialize request');
389
- console.error(chalk.blue('[DEBUG]'), 'Request:', JSON.stringify(request, null, 2));
498
+ mcpDebugStderr(chalk.blue('[DEBUG]'), 'initialize', JSON.stringify(request, null, 2));
390
499
  const response = {
391
500
  protocolVersion: '2024-11-05',
392
501
  capabilities: {
@@ -394,31 +503,30 @@ async function startMcpServer() {
394
503
  },
395
504
  serverInfo: {
396
505
  name: 'code-auditor',
397
- version: '1.0.0',
506
+ version: PACKAGE_VERSION,
398
507
  },
399
508
  };
400
- console.error(chalk.blue('[DEBUG]'), 'Initialize response:', JSON.stringify(response, null, 2));
509
+ mcpDebugStderr(chalk.blue('[DEBUG]'), 'initialize response', JSON.stringify(response, null, 2));
401
510
  return response;
402
511
  });
403
- // Handle tool execution
404
512
  server.setRequestHandler(CallToolRequestSchema, async (request) => {
405
- console.error(chalk.blue('[DEBUG]'), 'Received CallTool request');
406
- console.error(chalk.blue('[DEBUG]'), 'Request:', JSON.stringify(request, null, 2));
513
+ mcpDebugStderr(chalk.blue('[DEBUG]'), 'CallTool raw', JSON.stringify(request, null, 2));
407
514
  const { name, arguments: args } = request.params;
408
- console.error(chalk.blue('[DEBUG]'), `Tool name: ${name}`);
409
- console.error(chalk.blue('[DEBUG]'), `Tool arguments:`, JSON.stringify(args, null, 2));
410
- console.error(chalk.blue('[DEBUG]'), `Handling CallTool request for: ${name}`);
515
+ mcpDebugStderr(chalk.blue('[DEBUG]'), `CallTool ${name}`, JSON.stringify(args, null, 2));
516
+ const toolStartedAt = Date.now();
411
517
  try {
412
- console.error(chalk.blue('[DEBUG]'), `Starting tool execution for: ${name}`);
518
+ logMcpDebug('tool', `call ${name}`, {
519
+ argKeys: args && typeof args === 'object' ? Object.keys(args) : [],
520
+ pathArg: args?.path,
521
+ cwd: process.cwd()
522
+ });
413
523
  let result;
414
524
  switch (name) {
415
525
  case 'audit': {
416
526
  const auditPath = path.resolve(args.path || process.cwd());
417
527
  const indexFunctions = args.indexFunctions !== false; // Default true
418
528
  const generateCodeMap = args.generateCodeMap || false;
419
- // Check if path is a file or directory
420
- const stats = await fs.stat(auditPath).catch(() => null);
421
- const isFile = stats?.isFile() || false;
529
+ const { isFile } = await assertAuditPathExists(auditPath);
422
530
  // Get stored analyzer configs from database
423
531
  const db = CodeIndexDB.getInstance();
424
532
  await db.initialize();
@@ -436,12 +544,27 @@ async function startMcpServer() {
436
544
  indexFunctions,
437
545
  ...(isFile && { includePaths: [auditPath] }),
438
546
  ...(Object.keys(analyzerConfigs).length > 0 && { analyzerConfigs }),
547
+ progressCallback: (p) => {
548
+ if (p.phase === 'function-indexing' &&
549
+ typeof p.current === 'number' &&
550
+ typeof p.total === 'number' &&
551
+ p.total > 0 &&
552
+ p.current % 50 !== 0 &&
553
+ p.current !== p.total) {
554
+ return;
555
+ }
556
+ logMcpDebug('audit', p.message ?? p.phase ?? 'progress', {
557
+ phase: p.phase,
558
+ analyzer: p.analyzer,
559
+ current: p.current,
560
+ total: p.total
561
+ });
562
+ }
439
563
  };
440
- console.error(chalk.blue('[DEBUG]'), 'Creating audit runner with options:', JSON.stringify(options, null, 2));
564
+ mcpDebugStderr(chalk.blue('[DEBUG]'), 'audit runner options', JSON.stringify(options, null, 2));
441
565
  const runner = createAuditRunner(options);
442
- console.error(chalk.blue('[DEBUG]'), 'About to run audit...');
443
566
  const auditResult = await runner.run();
444
- console.error(chalk.blue('[DEBUG]'), 'Audit completed, result summary:', auditResult.summary);
567
+ mcpDebugStderr(chalk.blue('[DEBUG]'), 'audit summary', auditResult.summary);
445
568
  // Handle function indexing if enabled and functions were collected
446
569
  let indexingResult = null;
447
570
  if (indexFunctions && auditResult.metadata.fileToFunctionsMap) {
@@ -460,7 +583,7 @@ async function startMcpServer() {
460
583
  failed: 0,
461
584
  syncStats
462
585
  };
463
- console.error(chalk.blue('[INFO]'), `Synced functions: ${syncStats.added} added, ${syncStats.updated} updated, ${syncStats.removed} removed`);
586
+ mcpDebugStderr(chalk.blue('[INFO]'), `Synced functions: ${syncStats.added} added, ${syncStats.updated} updated, ${syncStats.removed} removed`);
464
587
  }
465
588
  catch (error) {
466
589
  console.error(chalk.yellow('[WARN]'), 'Failed to sync functions:', error);
@@ -507,7 +630,7 @@ async function startMcpServer() {
507
630
  sections: paginatedResult.summary.sectionsAvailable,
508
631
  documentationCoverage: documentation?.coverageScore
509
632
  };
510
- console.error(chalk.blue('[INFO]'), `Generated paginated code map: ${paginatedResult.summary.stats.totalFiles} files, ${paginatedResult.summary.totalSections} sections`);
633
+ mcpDebugStderr(chalk.blue('[INFO]'), `Generated paginated code map: ${paginatedResult.summary.stats.totalFiles} files, ${paginatedResult.summary.totalSections} sections`);
511
634
  }
512
635
  catch (error) {
513
636
  console.error(chalk.yellow('[WARN]'), 'Failed to generate code map:', error);
@@ -537,6 +660,7 @@ async function startMcpServer() {
537
660
  }
538
661
  case 'audit_health': {
539
662
  const auditPath = path.resolve(args.path || process.cwd());
663
+ await assertAuditPathExists(auditPath);
540
664
  const threshold = args.threshold || 70;
541
665
  const indexFunctions = args.indexFunctions !== false; // Default true
542
666
  const generateCodeMap = args.generateCodeMap !== false; // Default true
@@ -556,6 +680,22 @@ async function startMcpServer() {
556
680
  verbose: false,
557
681
  indexFunctions, // Pass the flag to the runner
558
682
  ...(Object.keys(analyzerConfigs).length > 0 && { analyzerConfigs }),
683
+ progressCallback: (p) => {
684
+ if (p.phase === 'function-indexing' &&
685
+ typeof p.current === 'number' &&
686
+ typeof p.total === 'number' &&
687
+ p.total > 0 &&
688
+ p.current % 50 !== 0 &&
689
+ p.current !== p.total) {
690
+ return;
691
+ }
692
+ logMcpDebug('audit_health', p.message ?? p.phase ?? 'progress', {
693
+ phase: p.phase,
694
+ analyzer: p.analyzer,
695
+ current: p.current,
696
+ total: p.total
697
+ });
698
+ }
559
699
  });
560
700
  const auditResult = await runner.run();
561
701
  const healthScore = calculateHealthScore(auditResult);
@@ -577,7 +717,7 @@ async function startMcpServer() {
577
717
  failed: 0,
578
718
  syncStats
579
719
  };
580
- console.error(chalk.blue('[INFO]'), `Synced functions: ${syncStats.added} added, ${syncStats.updated} updated, ${syncStats.removed} removed`);
720
+ mcpDebugStderr(chalk.blue('[INFO]'), `Synced functions: ${syncStats.added} added, ${syncStats.updated} updated, ${syncStats.removed} removed`);
581
721
  }
582
722
  catch (error) {
583
723
  console.error(chalk.yellow('[WARN]'), 'Failed to sync functions:', error);
@@ -624,7 +764,7 @@ async function startMcpServer() {
624
764
  sections: paginatedResult.summary.sectionsAvailable,
625
765
  documentationCoverage: documentation?.coverageScore
626
766
  };
627
- console.error(chalk.blue('[INFO]'), `Generated paginated code map: ${paginatedResult.summary.stats.totalFiles} files, ${paginatedResult.summary.totalSections} sections`);
767
+ mcpDebugStderr(chalk.blue('[INFO]'), `Generated paginated code map: ${paginatedResult.summary.stats.totalFiles} files, ${paginatedResult.summary.totalSections} sections`);
628
768
  }
629
769
  catch (error) {
630
770
  console.error(chalk.yellow('[WARN]'), 'Failed to generate code map:', error);
@@ -784,7 +924,7 @@ async function startMcpServer() {
784
924
  result = {
785
925
  mode: 'reset',
786
926
  success: true,
787
- message: 'Index cleared successfully'
927
+ message: 'Analysis-derived data cleared (functions, search index, cached audits, code maps, schemas). Project tasks, whitelist, and analyzer configs were preserved.'
788
928
  };
789
929
  break;
790
930
  }
@@ -983,6 +1123,11 @@ async function startMcpServer() {
983
1123
  }
984
1124
  break;
985
1125
  }
1126
+ case 'project_tasks': {
1127
+ const { handleProjectTasks } = await import('./mcp-tools/projectTasks.js');
1128
+ result = await handleProjectTasks((args || {}));
1129
+ break;
1130
+ }
986
1131
  default:
987
1132
  throw new Error(`Unknown tool: ${name}`);
988
1133
  }
@@ -994,30 +1139,31 @@ async function startMcpServer() {
994
1139
  },
995
1140
  ],
996
1141
  };
997
- console.error(chalk.blue('[DEBUG]'), `Tool ${name} executed successfully`);
998
- console.error(chalk.blue('[DEBUG]'), 'CallTool response:', JSON.stringify(response, null, 2).substring(0, 500) + '...');
1142
+ mcpDebugStderr(chalk.blue('[DEBUG]'), `Tool ${name} ok`, JSON.stringify(response, null, 2).substring(0, 500) + '...');
999
1143
  return response;
1000
1144
  }
1001
1145
  catch (error) {
1002
1146
  console.error(chalk.red('[ERROR]'), `Tool ${name} execution failed:`, error);
1003
1147
  console.error(chalk.red('[ERROR]'), 'Error stack:', error instanceof Error ? error.stack : 'No stack trace');
1148
+ logMcpDebug('tool', `call ${name} failed`, {
1149
+ ms: Date.now() - toolStartedAt,
1150
+ error: error instanceof Error ? error.message : String(error)
1151
+ });
1004
1152
  return {
1005
1153
  content: [
1006
1154
  {
1007
1155
  type: 'text',
1008
- text: JSON.stringify({
1009
- error: error instanceof Error ? error.message : 'Unknown error',
1010
- tool: name,
1011
- }),
1156
+ text: JSON.stringify(formatMcpToolErrorPayload(name, error), null, 2),
1012
1157
  },
1013
1158
  ],
1014
1159
  isError: true,
1015
1160
  };
1016
1161
  }
1162
+ finally {
1163
+ logMcpDebug('tool', `call ${name} finished`, { ms: Date.now() - toolStartedAt });
1164
+ }
1017
1165
  });
1018
- console.error(chalk.blue('[INFO]'), 'Request handlers configured');
1019
1166
  const transport = new StdioServerTransport();
1020
- console.error(chalk.blue('[INFO]'), 'Creating stdio transport...');
1021
1167
  // Add transport event handlers if available
1022
1168
  if (transport.onclose) {
1023
1169
  transport.onclose = () => {
@@ -1029,16 +1175,13 @@ async function startMcpServer() {
1029
1175
  console.error(chalk.red('[ERROR]'), 'Transport error:', error);
1030
1176
  };
1031
1177
  }
1032
- console.error(chalk.blue('[DEBUG]'), 'Connecting server to transport...');
1033
1178
  await server.connect(transport);
1034
- console.error(chalk.blue('[DEBUG]'), 'Server connected to transport');
1035
1179
  console.error(chalk.green('✓ Code Auditor MCP Server started'));
1036
- console.error(chalk.gray('Listening on stdio...'));
1037
- console.error(chalk.blue('[DEBUG]'), 'Server state after initialization:', {
1180
+ console.error(chalk.gray(`Listening on stdio · ${tools.length} tools · ${PACKAGE_VERSION}`));
1181
+ mcpDebugStderr(chalk.blue('[DEBUG]'), 'Server ready', {
1038
1182
  name: 'code-auditor',
1039
1183
  transport: 'stdio',
1040
- handlers: ['ListTools', 'CallTool', 'initialize'],
1041
- toolCount: tools.length,
1184
+ toolCount: tools.length
1042
1185
  });
1043
1186
  }
1044
1187
  function getAllViolations(result) {
@@ -1126,8 +1269,6 @@ process.stdin.on('error', (error) => {
1126
1269
  process.stdout.on('error', (error) => {
1127
1270
  console.error(chalk.red('[ERROR]'), 'stdout error:', error);
1128
1271
  });
1129
- // Start server
1130
- console.error(chalk.blue('[INFO]'), 'Initializing server...');
1131
1272
  startMcpServer().catch(error => {
1132
1273
  console.error(chalk.red('[ERROR]'), 'Failed to start MCP server:', error);
1133
1274
  console.error(chalk.red('[ERROR]'), 'Stack:', error.stack);