mcp-adr-analysis-server 2.7.39 → 2.7.41

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.
@@ -0,0 +1,4700 @@
1
+ /**
2
+ * MCP ADR Analysis Server
3
+ * Main entry point for the Model Context Protocol server
4
+ *
5
+ * This server provides Tools, Resources, and Prompts for analyzing
6
+ * Architectural Decision Records and project architecture.
7
+ */
8
+ import { Server } from '@modelcontextprotocol/sdk/server/index.js';
9
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
10
+ import { CallToolRequestSchema, ListToolsRequestSchema, ListResourcesRequestSchema, ReadResourceRequestSchema, ListPromptsRequestSchema, GetPromptRequestSchema, } from '@modelcontextprotocol/sdk/types.js';
11
+ import { readFileSync } from 'fs';
12
+ import { join } from 'path';
13
+ import { getCurrentDirCompat } from './utils/directory-compat.js';
14
+ import { McpAdrError } from './types/index.js';
15
+ import { maskMcpResponse, createMaskingConfig, } from './utils/output-masking.js';
16
+ import { loadConfig, validateProjectPath, createLogger, printConfigSummary, } from './utils/config.js';
17
+ import { KnowledgeGraphManager } from './utils/knowledge-graph-manager.js';
18
+ import { getEnhancedModeDefault, getKnowledgeEnhancementDefault, } from './utils/test-aware-defaults.js';
19
+ import { StateReinforcementManager } from './utils/state-reinforcement-manager.js';
20
+ import { ConversationMemoryManager } from './utils/conversation-memory-manager.js';
21
+ import { MemoryEntityManager } from './utils/memory-entity-manager.js';
22
+ import { RootManager } from './utils/root-manager.js';
23
+ import { ServerContextGenerator } from './utils/server-context-generator.js';
24
+ import { createNoOpContext } from './types/tool-context.js';
25
+ import { getToolListForMCP } from './tools/tool-dispatcher.js';
26
+ import { dispatchTool } from './tools/tool-dispatch.js';
27
+ import { shouldUseCEMCPDirective, getCEMCPDirective, formatDirectiveResponse, } from './tools/ce-mcp-tools.js';
28
+ import { loadAIConfig, isCEMCPEnabled } from './config/ai-config.js';
29
+ /**
30
+ * Get version from package.json
31
+ */
32
+ export function getPackageVersion() {
33
+ try {
34
+ // Handle both Jest environment and normal execution
35
+ const currentDir = getCurrentDirCompat();
36
+ // Strategy 1: Try multiple possible locations for package.json
37
+ const possiblePaths = [
38
+ join(currentDir, 'package.json'),
39
+ join(currentDir, '..', 'package.json'),
40
+ join(currentDir, '..', '..', 'package.json'),
41
+ join(process.cwd(), 'package.json'),
42
+ ];
43
+ for (const packageJsonPath of possiblePaths) {
44
+ try {
45
+ const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf-8'));
46
+ if (packageJson.name === 'mcp-adr-analysis-server') {
47
+ return packageJson.version;
48
+ }
49
+ }
50
+ catch {
51
+ // Try next path
52
+ }
53
+ }
54
+ // Strategy 2: Use process.env.npm_package_version if available (during npm scripts)
55
+ if (process.env['npm_package_version']) {
56
+ return process.env['npm_package_version'];
57
+ }
58
+ // Final fallback: Use generic version instead of hardcoded specific version
59
+ // This prevents the need to update this code when version changes
60
+ return 'unknown'; // Generic fallback - no longer tied to specific version
61
+ }
62
+ catch (error) {
63
+ console.error('Error reading package.json:', error);
64
+ return 'unknown'; // Generic fallback - no longer tied to specific version
65
+ }
66
+ }
67
+ /**
68
+ * Server configuration
69
+ */
70
+ const SERVER_INFO = {
71
+ name: 'mcp-adr-analysis-server',
72
+ version: getPackageVersion(),
73
+ description: 'MCP server for analyzing Architectural Decision Records and project architecture',
74
+ };
75
+ /**
76
+ * Main server class
77
+ */
78
+ export class McpAdrAnalysisServer {
79
+ server;
80
+ maskingConfig;
81
+ config;
82
+ logger;
83
+ kgManager;
84
+ stateReinforcementManager;
85
+ conversationMemoryManager;
86
+ memoryEntityManager;
87
+ rootManager;
88
+ contextGenerator;
89
+ constructor() {
90
+ // Load and validate configuration
91
+ this.config = loadConfig();
92
+ this.logger = createLogger(this.config);
93
+ this.kgManager = new KnowledgeGraphManager();
94
+ this.stateReinforcementManager = new StateReinforcementManager(this.kgManager);
95
+ this.conversationMemoryManager = new ConversationMemoryManager(this.kgManager);
96
+ this.memoryEntityManager = new MemoryEntityManager();
97
+ // Initialize root manager for file access control
98
+ this.rootManager = new RootManager(this.config.projectPath, this.config.adrDirectory);
99
+ // Initialize server context generator
100
+ this.contextGenerator = new ServerContextGenerator();
101
+ // Print configuration summary
102
+ printConfigSummary(this.config);
103
+ // Note: Validation will be done during startup
104
+ this.server = new Server(SERVER_INFO, {
105
+ capabilities: {
106
+ tools: {},
107
+ resources: {},
108
+ prompts: {},
109
+ },
110
+ });
111
+ this.maskingConfig = createMaskingConfig();
112
+ this.setupHandlers();
113
+ }
114
+ /**
115
+ * Validate configuration and project setup
116
+ */
117
+ async validateConfiguration() {
118
+ try {
119
+ await validateProjectPath(this.config.projectPath);
120
+ this.logger.info(`Project path validated: ${this.config.projectPath}`);
121
+ }
122
+ catch (error) {
123
+ const errorMessage = error instanceof Error ? error.message : String(error);
124
+ this.logger.error(`Configuration validation failed: ${errorMessage}`);
125
+ throw error;
126
+ }
127
+ }
128
+ /**
129
+ * Public health check method for testing
130
+ */
131
+ async healthCheck() {
132
+ await this.validateConfiguration();
133
+ this.logger.info('Health check completed successfully');
134
+ }
135
+ /**
136
+ * Setup MCP protocol handlers
137
+ *
138
+ * @description Configures all Model Context Protocol request handlers for the ADR Analysis Server.
139
+ * Implements the complete MCP specification including tools, resources, and prompts.
140
+ *
141
+ * @private
142
+ * @since 2.0.0
143
+ * @category MCP Protocol
144
+ */
145
+ setupHandlers() {
146
+ /**
147
+ * List Tools Handler - MCP Protocol Endpoint
148
+ *
149
+ * @description Returns the complete catalog of available tools for ADR analysis,
150
+ * research, validation, and deployment operations. Each tool includes comprehensive
151
+ * input schemas and descriptions for client integration.
152
+ *
153
+ * @returns {Promise<{tools: Array}>} Complete tool catalog with schemas
154
+ *
155
+ * @example
156
+ * ```typescript
157
+ * // MCP Client usage
158
+ * const tools = await mcpClient.listTools();
159
+ * console.log(tools.tools.length); // 20+ available tools
160
+ *
161
+ * // Find specific tool
162
+ * const researchTool = tools.tools.find(t => t.name === 'perform_research');
163
+ * console.log(researchTool.description); // Tool description
164
+ * ```
165
+ *
166
+ * @mcp-endpoint
167
+ * @category Tools
168
+ */
169
+ this.server.setRequestHandler(ListToolsRequestSchema, async () => {
170
+ return getToolListForMCP({ mode: 'full' });
171
+ });
172
+ /**
173
+ * Call Tool Handler - MCP Protocol Endpoint
174
+ */
175
+ this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
176
+ const { name, arguments: args } = request.params;
177
+ // Create context for progress notifications and logging
178
+ const context = {
179
+ info: (message) => {
180
+ this.logger.info(message);
181
+ // Note: MCP progress notifications will be available in future SDK versions
182
+ // For now, we log to server console for visibility
183
+ },
184
+ report_progress: (progress, total) => {
185
+ const percentage = total ? Math.round((progress / total) * 100) : progress;
186
+ this.logger.info(`Progress: ${percentage}%${total ? ` (${progress}/${total})` : ''}`);
187
+ },
188
+ warn: (message) => {
189
+ this.logger.warn(message);
190
+ },
191
+ error: (message) => {
192
+ this.logger.error(message);
193
+ },
194
+ };
195
+ try {
196
+ const safeArgs = args || {};
197
+ // CE-MCP Mode: Check if tool should return directive instead of executing
198
+ const aiConfig = loadAIConfig();
199
+ if (isCEMCPEnabled(aiConfig) &&
200
+ shouldUseCEMCPDirective(name, { mode: aiConfig.executionMode })) {
201
+ const directive = getCEMCPDirective(name, safeArgs);
202
+ if (directive) {
203
+ this.logger.info(`[CE-MCP] Returning directive for tool: ${name}`);
204
+ const directiveResponse = formatDirectiveResponse(directive);
205
+ // Record BEFORE returning. This early return skips the dispatch
206
+ // switch below and, with it, the trackToolExecution call on the
207
+ // success path -- so every tool in CE_MCP_DIRECTIVE_TOOLS was
208
+ // invisible to usage tracking whenever CE-MCP mode was on. All
209
+ // twelve of them, including `perform_research`, whose disposition
210
+ // ADR-023 defers *pending usage data*. See #1489.
211
+ //
212
+ // Deliberately not fatal: a directive is the tool's real answer, and
213
+ // failing to record it must never withhold it. trackToolExecution
214
+ // already swallows and warns internally; the catch here covers a
215
+ // throw before that boundary.
216
+ try {
217
+ await this.trackToolExecution(name, args, directiveResponse, true);
218
+ }
219
+ catch (trackingError) {
220
+ this.logger.warn(`[CE-MCP] Usage tracking failed for ${name}: ${trackingError instanceof Error ? trackingError.message : String(trackingError)}`);
221
+ }
222
+ return directiveResponse;
223
+ }
224
+ // Fall through to legacy execution if no directive available
225
+ this.logger.info(`[CE-MCP] No directive available for ${name}, using legacy path`);
226
+ }
227
+ const response = await dispatchTool(this, name, safeArgs, context);
228
+ // Track tool execution in knowledge graph
229
+ await this.trackToolExecution(name, args, response, true);
230
+ // Apply state reinforcement (Phase 2: Context Decay Mitigation) and content masking
231
+ // Also record conversation turn (Phase 3: Structured External Memory)
232
+ return await this.enrichResponseWithStateReinforcement(response, name, args);
233
+ }
234
+ catch (error) {
235
+ // Track failed execution
236
+ await this.trackToolExecution(name, args, {}, false, error instanceof Error ? error.message : String(error));
237
+ if (error instanceof McpAdrError) {
238
+ throw error;
239
+ }
240
+ throw new McpAdrError(`Tool execution failed: ${error instanceof Error ? error.message : String(error)}`, 'TOOL_EXECUTION_ERROR');
241
+ }
242
+ });
243
+ /**
244
+ * List Resources Handler - MCP Protocol Endpoint
245
+ *
246
+ * @description Returns available resources for client access including the
247
+ * architectural knowledge graph and project analysis data. Resources provide
248
+ * read-only access to server-managed data structures.
249
+ *
250
+ * @returns {Promise<{resources: Array}>} Available resources with URIs and descriptions
251
+ *
252
+ * @example
253
+ * ```typescript
254
+ * // List available resources
255
+ * const resources = await mcpClient.listResources();
256
+ * console.log(resources.resources.length); // Available resources
257
+ *
258
+ * // Find knowledge graph resource
259
+ * const kgResource = resources.resources.find(r =>
260
+ * r.uri === 'adr://architectural_knowledge_graph'
261
+ * );
262
+ * console.log(kgResource.name); // "Architectural Knowledge Graph"
263
+ * ```
264
+ *
265
+ * @mcp-endpoint
266
+ * @category Resources
267
+ */
268
+ this.server.setRequestHandler(ListResourcesRequestSchema, async () => {
269
+ return {
270
+ resources: [
271
+ // Existing resources (refactored to return data)
272
+ {
273
+ uri: 'adr://architectural_knowledge_graph',
274
+ name: 'Architectural Knowledge Graph',
275
+ description: 'Complete architectural knowledge graph with technologies, patterns, and relationships',
276
+ mimeType: 'application/json',
277
+ },
278
+ {
279
+ uri: 'adr://analysis_report',
280
+ name: 'Analysis Report',
281
+ description: 'Comprehensive project analysis report with metrics and recommendations',
282
+ mimeType: 'application/json',
283
+ },
284
+ {
285
+ uri: 'adr://adr_list',
286
+ name: 'ADR List',
287
+ description: 'List of all Architectural Decision Records with status and metadata',
288
+ mimeType: 'application/json',
289
+ },
290
+ // NEW Phase 1 Resources
291
+ {
292
+ uri: 'adr://todo_list',
293
+ name: 'Todo List',
294
+ description: 'Current project task list with status, priorities, and dependencies',
295
+ mimeType: 'application/json',
296
+ },
297
+ {
298
+ uri: 'adr://research_index',
299
+ name: 'Research Index',
300
+ description: 'Index of all research documents and findings with metadata',
301
+ mimeType: 'application/json',
302
+ },
303
+ {
304
+ uri: 'adr://rule_catalog',
305
+ name: 'Rule Catalog',
306
+ description: 'Catalog of all architectural and validation rules from ADRs and code',
307
+ mimeType: 'application/json',
308
+ },
309
+ {
310
+ uri: 'adr://rule_generation',
311
+ name: 'Rule Generation',
312
+ description: 'AI-powered rule generation from ADRs and code patterns. Supports query parameters: ?operation=generate|validate|create_set, ?source=adrs|patterns|both, ?knowledge=true|false, ?enhanced=true|false, ?format=json|yaml|both, ?comprehensive=true|false',
313
+ mimeType: 'application/json',
314
+ },
315
+ {
316
+ uri: 'adr://project_status',
317
+ name: 'Project Status',
318
+ description: 'Current project status and health metrics aggregated from all sources',
319
+ mimeType: 'application/json',
320
+ },
321
+ // NEW Phase 2 Templated Resources
322
+ {
323
+ uri: 'adr://adr/{id}',
324
+ name: 'ADR by ID',
325
+ description: 'Individual Architectural Decision Record by ID or title match',
326
+ mimeType: 'application/json',
327
+ },
328
+ {
329
+ uri: 'adr://research/{topic}',
330
+ name: 'Research by Topic',
331
+ description: 'Research documents filtered by topic with full content',
332
+ mimeType: 'application/json',
333
+ },
334
+ {
335
+ uri: 'adr://todo/{task_id}',
336
+ name: 'Todo by Task ID',
337
+ description: 'Individual task details by ID or title match with dependencies and history',
338
+ mimeType: 'application/json',
339
+ },
340
+ {
341
+ uri: 'adr://rule/{rule_id}',
342
+ name: 'Rule by ID',
343
+ description: 'Individual architectural rule by ID or name match with violations and usage stats',
344
+ mimeType: 'application/json',
345
+ },
346
+ // NEW Phase 3 Advanced Resources
347
+ {
348
+ uri: 'adr://deployment_status',
349
+ name: 'Deployment Status',
350
+ description: 'Current deployment state with health checks, build status, and readiness score',
351
+ mimeType: 'application/json',
352
+ },
353
+ {
354
+ uri: 'adr://environment_analysis',
355
+ name: 'Environment Analysis',
356
+ description: 'System environment details including platform, dependencies, and capabilities',
357
+ mimeType: 'application/json',
358
+ },
359
+ {
360
+ uri: 'adr://memory_snapshots',
361
+ name: 'Memory Snapshots',
362
+ description: 'Knowledge graph snapshots with statistics, insights, and relationship data',
363
+ mimeType: 'application/json',
364
+ },
365
+ {
366
+ uri: 'adr://project_metrics',
367
+ name: 'Project Metrics',
368
+ description: 'Code metrics and quality scores including codebase stats, quality assessment, and git metrics',
369
+ mimeType: 'application/json',
370
+ },
371
+ {
372
+ uri: 'adr://technology/{name}',
373
+ name: 'Technology by Name',
374
+ description: 'Individual technology analysis by name with usage, relationships, and adoption status',
375
+ mimeType: 'application/json',
376
+ },
377
+ {
378
+ uri: 'adr://pattern/{name}',
379
+ name: 'Pattern by Name',
380
+ description: 'Individual pattern analysis by name with quality metrics, relationships, and examples',
381
+ mimeType: 'application/json',
382
+ },
383
+ // NEW Phase 4 Final Resources
384
+ {
385
+ uri: 'adr://deployment_history',
386
+ name: 'Deployment History',
387
+ description: 'Historical deployment data with trends, failure analysis, and patterns. Supports query parameters: ?period=7d|30d|90d|1y|all, ?environment=production|staging|development|all, ?includeFailures=true|false, ?includeMetrics=true|false, ?format=summary|detailed',
388
+ mimeType: 'application/json',
389
+ },
390
+ {
391
+ uri: 'adr://release_history',
392
+ name: 'Release History',
393
+ description: 'Release tracking state with releases mapped to ADRs, milestones, and project metadata. Shows release timeline, ADR-to-release mappings with confidence scores, and unmapped ADRs.',
394
+ mimeType: 'application/json',
395
+ },
396
+ {
397
+ uri: 'adr://code_quality',
398
+ name: 'Code Quality',
399
+ description: 'Comprehensive code quality assessment with metrics, issues, and recommendations. Supports query parameters: ?scope=full|changes|critical, ?includeMetrics=true|false, ?includeRecommendations=true|false, ?threshold=0-100, ?format=summary|detailed',
400
+ mimeType: 'application/json',
401
+ },
402
+ // NEW Phase 5 Validated Pattern Resources
403
+ {
404
+ uri: 'adr://validated_patterns',
405
+ name: 'Validated Patterns Catalog',
406
+ description: 'Complete catalog of validated deployment patterns for different platforms (OpenShift, Kubernetes, Docker, Node.js, Python, MCP, A2A) with bill of materials, deployment phases, validation checks, and authoritative sources',
407
+ mimeType: 'application/json',
408
+ },
409
+ {
410
+ uri: 'adr://validated_pattern/{platform}',
411
+ name: 'Validated Pattern by Platform',
412
+ description: 'Individual validated pattern by platform type (openshift, kubernetes, docker, nodejs, python, mcp, a2a) with complete bill of materials, deployment phases, validation checks, health checks, and authoritative sources for LLM research',
413
+ mimeType: 'application/json',
414
+ },
415
+ {
416
+ uri: 'adr://pattern_sources/{platform}',
417
+ name: 'Pattern Authoritative Sources',
418
+ description: 'Authoritative documentation and repository sources for a specific platform pattern, prioritized by importance with query instructions for LLMs',
419
+ mimeType: 'application/json',
420
+ },
421
+ {
422
+ uri: 'adr://pattern_base_code/{platform}',
423
+ name: 'Pattern Base Code Repository',
424
+ description: 'Base code repository information for a platform pattern including URL, integration instructions, required files, and script entrypoint',
425
+ mimeType: 'application/json',
426
+ },
427
+ // NEW Knowledge Graph Resource (ADR-018)
428
+ {
429
+ uri: 'knowledge://graph',
430
+ name: 'Knowledge Graph',
431
+ description: 'Read-only knowledge graph structure with nodes (intents, ADRs, tools, code files) and edges (relationships). Zero token cost for querying graph state. Use update_knowledge tool to modify.',
432
+ mimeType: 'application/json',
433
+ },
434
+ ],
435
+ };
436
+ });
437
+ /**
438
+ * Read Resource Handler - MCP Protocol Endpoint
439
+ *
440
+ * @description Reads specific resource content by URI. Provides access to
441
+ * architectural knowledge graphs, project analysis data, and other server-managed
442
+ * resources with appropriate content masking applied.
443
+ *
444
+ * @param {ReadResourceRequest} request - MCP resource read request
445
+ * @param {string} request.params.uri - Resource URI to read
446
+ *
447
+ * @returns {Promise<ReadResourceResult>} Resource content with metadata
448
+ *
449
+ * @throws {McpAdrError} When resource URI is invalid or access fails
450
+ *
451
+ * @example
452
+ * ```typescript
453
+ * // Read knowledge graph resource
454
+ * const kgData = await mcpClient.readResource(
455
+ * 'adr://architectural_knowledge_graph'
456
+ * );
457
+ * console.log(kgData.contents); // Knowledge graph JSON
458
+ * ```
459
+ *
460
+ * @mcp-endpoint
461
+ * @category Resources
462
+ */
463
+ this.server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
464
+ const { uri } = request.params;
465
+ try {
466
+ const response = await this.readResource(uri);
467
+ return await this.applyOutputMasking(response);
468
+ }
469
+ catch (error) {
470
+ if (error instanceof McpAdrError) {
471
+ throw error;
472
+ }
473
+ throw new McpAdrError(`Resource reading failed: ${error instanceof Error ? error.message : String(error)}`, 'RESOURCE_ERROR');
474
+ }
475
+ });
476
+ /**
477
+ * List Prompts Handler - MCP Protocol Endpoint
478
+ *
479
+ * @description Returns available prompt templates for ADR analysis, research,
480
+ * and architectural decision support. Prompts can be executed directly or
481
+ * used as templates for custom implementations.
482
+ *
483
+ * @returns {Promise<{prompts: Array}>} Available prompt templates with metadata
484
+ *
485
+ * @example
486
+ * ```typescript
487
+ * // List available prompts
488
+ * const prompts = await mcpClient.listPrompts();
489
+ * console.log(prompts.prompts.length); // Available prompt templates
490
+ *
491
+ * // Find ADR analysis prompt
492
+ * const adrPrompt = prompts.prompts.find(p =>
493
+ * p.name === 'adr_analysis_prompt'
494
+ * );
495
+ * console.log(adrPrompt.description); // Prompt description
496
+ * ```
497
+ *
498
+ * @mcp-endpoint
499
+ * @category Prompts
500
+ */
501
+ this.server.setRequestHandler(ListPromptsRequestSchema, async () => {
502
+ const { allPrompts } = await import('./prompts/index.js');
503
+ return {
504
+ prompts: allPrompts.map(prompt => ({
505
+ name: prompt.name,
506
+ description: prompt.description,
507
+ arguments: prompt.arguments,
508
+ })),
509
+ };
510
+ });
511
+ /**
512
+ * Get Prompt Handler - MCP Protocol Endpoint
513
+ *
514
+ * @description Executes specific prompt templates with provided arguments.
515
+ * Returns formatted prompts ready for AI execution or further processing.
516
+ * Supports dynamic argument injection and template customization.
517
+ *
518
+ * @param {GetPromptRequest} request - MCP prompt execution request
519
+ * @param {string} request.params.name - Prompt template name
520
+ * @param {Object} request.params.arguments - Template-specific arguments
521
+ *
522
+ * @returns {Promise<GetPromptResult>} Formatted prompt with metadata
523
+ *
524
+ * @throws {McpAdrError} When prompt template is not found or arguments are invalid
525
+ *
526
+ * @example
527
+ * ```typescript
528
+ * // Execute ADR analysis prompt
529
+ * const prompt = await mcpClient.getPrompt('adr_analysis_prompt', {
530
+ * adrPath: 'docs/adrs/0001-auth.md',
531
+ * projectContext: 'microservices architecture'
532
+ * });
533
+ *
534
+ * console.log(prompt.messages); // Formatted prompt messages
535
+ * ```
536
+ *
537
+ * @example
538
+ * ```typescript
539
+ * // Execute research prompt
540
+ * const researchPrompt = await mcpClient.getPrompt('research_question_prompt', {
541
+ * domain: 'authentication',
542
+ * complexity: 'advanced'
543
+ * });
544
+ *
545
+ * console.log(researchPrompt.messages[0].content); // Research prompt
546
+ * ```
547
+ *
548
+ * @mcp-endpoint
549
+ * @category Prompts
550
+ * @category Execution
551
+ */
552
+ this.server.setRequestHandler(GetPromptRequestSchema, async (request) => {
553
+ const { name, arguments: args } = request.params;
554
+ try {
555
+ const { allPrompts } = await import('./prompts/index.js');
556
+ const prompt = allPrompts.find(p => p.name === name);
557
+ if (!prompt) {
558
+ throw new McpAdrError(`Unknown prompt: ${name}`, 'UNKNOWN_PROMPT');
559
+ }
560
+ // Simple template rendering (replace {{variable}} with values)
561
+ let renderedTemplate = prompt.template;
562
+ if (args) {
563
+ for (const [key, value] of Object.entries(args)) {
564
+ const regex = new RegExp(`{{${key}}}`, 'g');
565
+ renderedTemplate = renderedTemplate.replace(regex, String(value));
566
+ }
567
+ }
568
+ const response = {
569
+ description: prompt.description,
570
+ messages: [
571
+ {
572
+ role: 'user',
573
+ content: {
574
+ type: 'text',
575
+ text: renderedTemplate,
576
+ },
577
+ },
578
+ ],
579
+ };
580
+ return await this.applyOutputMasking(response);
581
+ }
582
+ catch (error) {
583
+ if (error instanceof McpAdrError) {
584
+ throw error;
585
+ }
586
+ throw new McpAdrError(`Prompt execution failed: ${error instanceof Error ? error.message : String(error)}`, 'PROMPT_EXECUTION_ERROR');
587
+ }
588
+ });
589
+ }
590
+ /**
591
+ * Tool implementations
592
+ */
593
+ async checkAIExecutionStatus(_args) {
594
+ try {
595
+ const { getAIExecutionStatus } = await import('./utils/prompt-execution.js');
596
+ const status = getAIExecutionStatus();
597
+ return {
598
+ content: [
599
+ {
600
+ type: 'text',
601
+ text: `# AI Execution Status Diagnostic
602
+
603
+ > **Note**: As of Phase 5, this server uses CE-MCP (Claude-Enriched MCP) mode by default.
604
+ > In CE-MCP mode, tools return orchestration directives that the host LLM executes directly,
605
+ > eliminating the need for external API calls. The configuration below applies to legacy mode only.
606
+
607
+ ## Current Configuration
608
+ - **AI Execution Enabled**: ${status.isEnabled ? '✅ YES' : '❌ NO'}
609
+ - **Has API Key**: ${status.hasApiKey ? '✅ YES' : '❌ NO'}
610
+ - **Execution Mode**: ${status.executionMode}
611
+ - **AI Model**: ${status.model}
612
+
613
+ ${
614
+ // CE-MCP is the DEFAULT mode and needs no API key. Reporting the absence of
615
+ // one as an "Issue Detected" -- immediately after saying no external API call
616
+ // is needed -- told every new user to go and buy a key they do not need.
617
+ // Legacy configuration is only a problem for someone who asked for it. (#1414)
618
+ status.executionMode === 'ce-mcp'
619
+ ? `## ✅ Running in CE-MCP mode
620
+
621
+ No API key is required. Tools return orchestration directives that your host LLM
622
+ executes directly, which is why **AI Execution Enabled: NO** above is expected and
623
+ correct rather than a fault.
624
+
625
+ Note that only some tools currently return a directive; the rest return their
626
+ result directly. See ADR-014 and ADR-021.
627
+
628
+ Legacy OpenRouter execution is off by design. You only need the configuration
629
+ below if you deliberately want that older path.`
630
+ : status.reason
631
+ ? `## ⚠️ Issue Detected
632
+ **Problem**: ${status.reason}
633
+
634
+ ## Solution
635
+ ${!status.hasApiKey
636
+ ? `
637
+ 1. Get an OpenRouter API key from https://openrouter.ai/keys
638
+ 2. Add it to your MCP configuration:
639
+ \`\`\`json
640
+ {
641
+ "mcpServers": {
642
+ "adr-analysis": {
643
+ "command": "mcp-adr-analysis-server",
644
+ "env": {
645
+ "OPENROUTER_API_KEY": "your_api_key_here",
646
+ "EXECUTION_MODE": "full",
647
+ "AI_MODEL": "anthropic/claude-3-sonnet"
648
+ }
649
+ }
650
+ }
651
+ }
652
+ \`\`\`
653
+ 3. Restart your MCP client (Claude Desktop, etc.)
654
+ `
655
+ : status.executionMode !== 'full'
656
+ ? `
657
+ 1. Update your MCP configuration to set EXECUTION_MODE to "full":
658
+ \`\`\`json
659
+ {
660
+ "mcpServers": {
661
+ "adr-analysis": {
662
+ "env": {
663
+ "EXECUTION_MODE": "full"
664
+ }
665
+ }
666
+ }
667
+ }
668
+ \`\`\`
669
+ 2. Restart your MCP client
670
+ `
671
+ : ''}`
672
+ : `## ✅ Configuration Looks Good!
673
+
674
+ AI execution is properly configured. Tools should return actual results instead of prompts.
675
+
676
+ If you're still seeing prompts instead of results, try:
677
+ 1. Restart your MCP client
678
+ 2. Check your OpenRouter API key has sufficient credits
679
+ 3. Verify network connectivity to OpenRouter.ai`}
680
+
681
+ ## Environment Variables Expected
682
+ - **OPENROUTER_API_KEY**: Your OpenRouter API key
683
+ - **EXECUTION_MODE**: Set to "full" for AI execution
684
+ - **AI_MODEL**: AI model to use (optional, defaults to claude-3-sonnet)
685
+
686
+ ## Testing
687
+ After fixing the configuration, try calling \`suggest_adrs\` - it should return actual ADR suggestions instead of prompts.
688
+ `,
689
+ },
690
+ ],
691
+ };
692
+ }
693
+ catch (error) {
694
+ return {
695
+ content: [
696
+ {
697
+ type: 'text',
698
+ text: `# AI Execution Status Check Failed
699
+
700
+ **Error**: ${error instanceof Error ? error.message : String(error)}
701
+
702
+ This diagnostic tool helps identify why tools return prompts instead of actual results.
703
+
704
+ ## Manual Check
705
+ Verify these environment variables are set in your MCP configuration:
706
+ - OPENROUTER_API_KEY
707
+ - EXECUTION_MODE=full
708
+ - AI_MODEL (optional)
709
+ `,
710
+ },
711
+ ],
712
+ };
713
+ }
714
+ }
715
+ async getWorkflowGuidance(args) {
716
+ const { goal, projectContext, availableAssets = [], timeframe = 'thorough_review', primaryConcerns = [], } = args;
717
+ try {
718
+ const workflowPrompt = `
719
+ # Workflow Guidance & Tool Recommendation System
720
+
721
+ ## User Context Analysis
722
+ - **Goal**: ${goal}
723
+ - **Project Context**: ${projectContext}
724
+ - **Available Assets**: ${availableAssets.length > 0 ? availableAssets.join(', ') : 'None specified'}
725
+ - **Timeframe**: ${timeframe}
726
+ - **Primary Concerns**: ${primaryConcerns.length > 0 ? primaryConcerns.join(', ') : 'General analysis'}
727
+
728
+ ## Available MCP Tools (24 Total)
729
+
730
+ ### 🎯 **Core Analysis Tools** (AI-Powered ✅)
731
+ 1. **analyze_project_ecosystem** - Comprehensive technology and pattern detection
732
+ 2. **get_architectural_context** - Generate intelligent architectural insights + ADR setup
733
+ 3. **generate_adrs_from_prd** - Convert requirements to structured ADRs
734
+ 4. **analyze_content_security** - Detect sensitive information patterns
735
+
736
+ ### 📋 **ADR Management Tools** (AI-Powered ✅)
737
+ 5. **suggest_adrs** - Auto-suggest ADRs from implicit decisions
738
+ 6. **generate_adr_from_decision** - Create ADRs from specific decisions
739
+ 7. **discover_existing_adrs** - Intelligent ADR discovery and analysis
740
+
741
+ ### 🔍 **Research & Documentation Tools** (AI-Powered ✅)
742
+ 8. **generate_research_questions** - Create context-aware research questions
743
+ 9. **incorporate_research** - Integrate research findings into decisions
744
+ 10. **create_research_template** - Generate research documentation templates
745
+
746
+ ### 🛡️ **Security & Compliance Tools** (AI-Powered ✅)
747
+ 11. **generate_content_masking** - Intelligent content masking and protection
748
+ 12. **configure_custom_patterns** - Customize security and masking settings
749
+ 13. **apply_basic_content_masking** - Basic content masking (fallback)
750
+ 14. **validate_content_masking** - Validate masking effectiveness
751
+
752
+ ### 🏗️ **Rule & Governance Tools** (AI-Powered ✅)
753
+ 16. **generate_rules** - Extract architectural rules from ADRs
754
+ 17. **validate_rules** - Validate code against architectural rules
755
+ 18. **create_rule_set** - Create comprehensive rule management systems
756
+
757
+ ### 🚀 **Deployment & Environment Tools** (AI-Powered ✅)
758
+ 19. **analyze_environment** - Environment analysis and optimization
759
+ 20. **analyze_deployment_progress** - Deployment tracking and verification
760
+
761
+ ### ⚙️ **Utility & Management Tools**
762
+ 21. **manage_cache** - Cache management and optimization
763
+ 22. **configure_output_masking** - Configure global output masking
764
+ 23. **request_action_confirmation** - Interactive user confirmation workflows
765
+ 24. **get_workflow_guidance** - This tool - intelligent workflow advisor
766
+
767
+ ## Workflow Recommendation Instructions
768
+
769
+ Based on the user's goal, project context, available assets, timeframe, and concerns, provide:
770
+
771
+ ### 1. **Recommended Tool Sequence**
772
+ Provide a step-by-step workflow with:
773
+ - **Tool Name**: Exact tool to call
774
+ - **Purpose**: Why this tool is needed
775
+ - **Expected Outcome**: What it will deliver
776
+ - **Parameters**: Suggested parameters for the tool call
777
+ - **Success Criteria**: How to know it worked
778
+
779
+ ### 2. **Alternative Workflows**
780
+ Provide 2-3 alternative approaches based on:
781
+ - Different time constraints
782
+ - Different priorities
783
+ - Different starting points
784
+
785
+ ### 3. **Expected Timeline & Effort**
786
+ For each recommended workflow:
787
+ - **Estimated Time**: How long each step takes
788
+ - **Effort Level**: Low/Medium/High effort required
789
+ - **Dependencies**: Which steps must be completed first
790
+
791
+ ### 4. **Success Metrics**
792
+ Define how to measure success:
793
+ - **Immediate Indicators**: Quick wins and early signals
794
+ - **Progress Milestones**: Key checkpoints
795
+ - **Final Outcomes**: Ultimate success criteria
796
+
797
+ ### 5. **Common Pitfalls & Tips**
798
+ - **What to Avoid**: Common mistakes in this workflow
799
+ - **Pro Tips**: Best practices for maximum effectiveness
800
+ - **Troubleshooting**: What to do if steps fail
801
+
802
+ ## Common Workflow Patterns
803
+
804
+ ### **New Project Setup**
805
+ 1. analyze_project_ecosystem → 2. get_architectural_context → 3. suggest_adrs → 4. generate_adr_from_decision
806
+
807
+ ### **Existing Project Analysis**
808
+ 1. discover_existing_adrs → 2. get_architectural_context → 3. validate_rules
809
+
810
+ ### **Security Audit**
811
+ 1. analyze_content_security → 2. generate_content_masking → 3. configure_custom_patterns → 4. validate_content_masking
812
+
813
+ ### **PRD to Implementation**
814
+ 1. generate_adrs_from_prd → 2. analyze_deployment_progress
815
+
816
+ ### **Legacy Modernization**
817
+ 1. analyze_project_ecosystem → 2. get_architectural_context → 3. suggest_adrs → 4. generate_rules → 5. validate_rules
818
+
819
+ ## Output Format
820
+
821
+ Provide a comprehensive workflow guide that includes:
822
+
823
+ 1. **🎯 Recommended Primary Workflow** (step-by-step with tool calls)
824
+ 2. **🔄 Alternative Approaches** (2-3 different paths)
825
+ 3. **⏱️ Timeline & Effort Estimates** (realistic expectations)
826
+ 4. **📊 Success Metrics** (how to measure progress)
827
+ 5. **💡 Pro Tips & Best Practices** (maximize effectiveness)
828
+ 6. **⚠️ Common Pitfalls** (what to avoid)
829
+
830
+ Make the guidance **actionable, specific, and outcome-focused** so the user can immediately start executing the recommended workflow.
831
+ `;
832
+ // Execute the workflow guidance with AI if enabled
833
+ const { executePromptWithFallback, formatMCPResponse } = await import('./utils/prompt-execution.js');
834
+ const executionResult = await executePromptWithFallback(workflowPrompt, 'Analyze the user context and provide intelligent workflow guidance with specific tool recommendations.', {
835
+ temperature: 0.1,
836
+ maxTokens: 6000,
837
+ systemPrompt: `You are an expert workflow advisor for the MCP ADR Analysis Server.
838
+ Your role is to analyze user goals and project context, then recommend the optimal sequence of tools to achieve their objectives efficiently.
839
+ Provide specific, actionable guidance with clear tool sequences, expected outcomes, and success criteria.
840
+ Focus on practical workflows that deliver measurable results.`,
841
+ });
842
+ if (executionResult.isAIGenerated) {
843
+ // AI execution successful - return actual workflow guidance
844
+ return formatMCPResponse({
845
+ ...executionResult,
846
+ content: `# Workflow Guidance & Tool Recommendations
847
+
848
+ ## Your Context
849
+ - **Goal**: ${goal}
850
+ - **Project Context**: ${projectContext}
851
+ - **Available Assets**: ${availableAssets.length > 0 ? availableAssets.join(', ') : 'None specified'}
852
+ - **Timeframe**: ${timeframe}
853
+ - **Primary Concerns**: ${primaryConcerns.length > 0 ? primaryConcerns.join(', ') : 'General analysis'}
854
+
855
+ ## AI-Generated Workflow Guidance
856
+
857
+ ${executionResult.content}
858
+
859
+ ## Quick Reference: Available Tools
860
+
861
+ **Core Analysis**: analyze_project_ecosystem, get_architectural_context, generate_adrs_from_prd, analyze_content_security
862
+ **ADR Management**: suggest_adrs, generate_adr_from_decision, discover_existing_adrs
863
+ **Security**: generate_content_masking, configure_custom_patterns, validate_content_masking
864
+ **Governance**: generate_rules, validate_rules, create_rule_set
865
+ **Environment**: analyze_environment, analyze_deployment_progress
866
+ **Utilities**: manage_cache, configure_output_masking, check_ai_execution_status
867
+
868
+ ## Next Steps
869
+
870
+ 1. **Start with the recommended primary workflow** above
871
+ 2. **Call the first tool** with the suggested parameters
872
+ 3. **Review the results** and proceed to the next step
873
+ 4. **Track progress** using the success metrics provided
874
+ 5. **Adjust as needed** based on your specific findings
875
+
876
+ This guidance is tailored to your specific context and goals for maximum effectiveness!
877
+ `,
878
+ });
879
+ }
880
+ else {
881
+ // Fallback to prompt-only mode
882
+ return {
883
+ content: [
884
+ {
885
+ type: 'text',
886
+ text: workflowPrompt,
887
+ },
888
+ ],
889
+ };
890
+ }
891
+ }
892
+ catch (error) {
893
+ throw new McpAdrError(`Failed to generate workflow guidance: ${error instanceof Error ? error.message : String(error)}`, 'WORKFLOW_ERROR');
894
+ }
895
+ }
896
+ async getDevelopmentGuidance(args) {
897
+ const { developmentPhase, adrsToImplement = [], technologyStack = [], currentProgress = '', teamContext = { size: 'small_team', experienceLevel: 'mixed' }, timeline = '', focusAreas = [], } = args;
898
+ try {
899
+ // Use actual ADR discovery if ADRs are specified
900
+ let adrAnalysisPrompt = '';
901
+ if (adrsToImplement.length > 0) {
902
+ const { getAdrDirectoryPath } = await import('./utils/config.js');
903
+ const { discoverAdrsInDirectory } = await import('./utils/adr-discovery.js');
904
+ const absoluteAdrPath = getAdrDirectoryPath(this.config);
905
+ const discoveryResult = await discoverAdrsInDirectory(absoluteAdrPath, this.config.projectPath, {
906
+ includeContent: true,
907
+ includeTimeline: false,
908
+ });
909
+ // Filter ADRs to only those specified for implementation
910
+ const targetAdrs = discoveryResult.adrs.filter(adr => adrsToImplement.some((target) => adr.title.toLowerCase().includes(target.toLowerCase()) ||
911
+ adr.filename.toLowerCase().includes(target.toLowerCase())));
912
+ adrAnalysisPrompt = `
913
+ ## ADR Analysis for Implementation
914
+
915
+ **ADRs to Implement**: ${adrsToImplement.join(', ')}
916
+ **ADR Directory**: ${absoluteAdrPath}
917
+ **Found ${targetAdrs.length} matching ADRs**
918
+
919
+ ${targetAdrs
920
+ .map(adr => `
921
+ ### ${adr.title}
922
+ - **File**: ${adr.filename}
923
+ - **Status**: ${adr.status}
924
+ - **Context**: ${adr.context}
925
+ - **Decision**: ${adr.decision}
926
+ - **Consequences**: ${adr.consequences}
927
+ `)
928
+ .join('\n')}
929
+ `;
930
+ }
931
+ const developmentPrompt = `
932
+ # Development Guidance & Implementation Roadmap
933
+
934
+ ## Development Context
935
+ - **Development Phase**: ${developmentPhase}
936
+ - **Technology Stack**: ${technologyStack.length > 0 ? technologyStack.join(', ') : 'Not specified'}
937
+ - **Current Progress**: ${currentProgress || 'Starting fresh'}
938
+ - **Team Size**: ${teamContext.size}
939
+ - **Team Experience**: ${teamContext.experienceLevel}
940
+ - **Timeline**: ${timeline || 'Not specified'}
941
+ - **Focus Areas**: ${focusAreas.length > 0 ? focusAreas.join(', ') : 'General development'}
942
+
943
+ ${adrAnalysisPrompt}
944
+
945
+ ## Development Guidance Instructions
946
+
947
+ Based on the development context, ADRs to implement, and technology stack, provide comprehensive development guidance including:
948
+
949
+ ### 1. **Implementation Roadmap**
950
+ Create a detailed development plan with:
951
+ - **Phase-by-Phase Breakdown**: Logical development phases
952
+ - **Task Prioritization**: Order tasks by dependencies and impact
953
+ - **Milestone Definition**: Clear checkpoints and deliverables
954
+ - **Risk Assessment**: Potential blockers and mitigation strategies
955
+
956
+ ### 2. **Code Structure & Architecture**
957
+ Provide specific guidance on:
958
+ - **Project Structure**: How to organize code files and directories
959
+ - **Module Architecture**: How to structure components/modules
960
+ - **Design Patterns**: Which patterns to use and where
961
+ - **Code Organization**: Separation of concerns and layering
962
+
963
+ ### 3. **Implementation Patterns & Best Practices**
964
+ For each technology in the stack, provide:
965
+ - **Framework-Specific Patterns**: Best practices for the chosen frameworks
966
+ - **API Design**: How to structure APIs and endpoints
967
+ - **Data Layer**: Database schema and data access patterns
968
+ - **State Management**: How to handle application state
969
+ - **Error Handling**: Consistent error handling strategies
970
+
971
+ ### 4. **ADR-to-Code Translation**
972
+ For each ADR to implement:
973
+ - **Implementation Tasks**: Specific coding tasks derived from the ADR
974
+ - **Code Examples**: Pseudo-code or pattern examples
975
+ - **Integration Points**: How this ADR affects other parts of the system
976
+ - **Validation Criteria**: How to verify the ADR is properly implemented
977
+
978
+ ### 5. **Testing Strategy**
979
+ Comprehensive testing approach:
980
+ - **Unit Testing**: What to test and how
981
+ - **Integration Testing**: API and component integration tests
982
+ - **End-to-End Testing**: User workflow testing
983
+ - **Performance Testing**: Load and performance validation
984
+ - **Security Testing**: Security validation approaches
985
+
986
+ ### 6. **Development Workflow**
987
+ Team-specific guidance:
988
+ - **Git Workflow**: Branching strategy and code review process
989
+ - **CI/CD Pipeline**: Automated testing and deployment
990
+ - **Code Quality**: Linting, formatting, and quality gates
991
+ - **Documentation**: What to document and how
992
+
993
+ ### 7. **Quality Gates & Checkpoints**
994
+ Define success criteria:
995
+ - **Code Quality Metrics**: Coverage, complexity, maintainability
996
+ - **Performance Benchmarks**: Response times, throughput targets
997
+ - **Security Checkpoints**: Security validation at each phase
998
+ - **Architectural Compliance**: Adherence to ADR decisions
999
+
1000
+ ### 8. **Technology-Specific Implementation**
1001
+ For each technology in the stack, provide:
1002
+ - **Setup Instructions**: Environment and tooling setup
1003
+ - **Configuration**: Framework and tool configuration
1004
+ - **Optimization**: Performance and build optimization
1005
+ - **Deployment**: Technology-specific deployment considerations
1006
+
1007
+ ## Expected Output Format
1008
+
1009
+ Provide a comprehensive development guide that includes:
1010
+
1011
+ ### 📋 **1. Development Roadmap**
1012
+ - **Phase 1-N**: Logical development phases with tasks
1013
+ - **Dependencies**: Task dependencies and critical path
1014
+ - **Timeline**: Estimated effort and duration
1015
+ - **Milestones**: Key deliverables and checkpoints
1016
+
1017
+ ### 🏗️ **2. Implementation Guide**
1018
+ - **Code Structure**: Detailed project organization
1019
+ - **Design Patterns**: Specific patterns to implement
1020
+ - **API Design**: Endpoint structure and conventions
1021
+ - **Data Architecture**: Database and data flow design
1022
+
1023
+ ### 🧪 **3. Testing & Quality Strategy**
1024
+ - **Test Types**: Unit, integration, e2e testing approach
1025
+ - **Quality Gates**: Code quality and performance criteria
1026
+ - **Automation**: CI/CD and automated testing setup
1027
+
1028
+ ### 🚀 **4. Deployment & Operations**
1029
+ - **Environment Setup**: Development, staging, production
1030
+ - **Deployment Pipeline**: Automated deployment process
1031
+ - **Monitoring**: Logging, metrics, and alerting
1032
+ - **Maintenance**: Ongoing maintenance and updates
1033
+
1034
+ ### 📊 **5. Progress Tracking**
1035
+ - **Success Metrics**: How to measure development progress
1036
+ - **Quality Indicators**: Code quality and performance metrics
1037
+ - **Milestone Validation**: How to verify milestone completion
1038
+ - **Risk Monitoring**: Early warning signs and mitigation
1039
+
1040
+ ### 💡 **6. Team-Specific Recommendations**
1041
+ Based on team size (${teamContext.size}) and experience (${teamContext.experienceLevel}):
1042
+ - **Workflow Adaptations**: Process adjustments for team context
1043
+ - **Skill Development**: Areas for team skill building
1044
+ - **Tool Recommendations**: Development tools and practices
1045
+ - **Communication**: Coordination and documentation practices
1046
+
1047
+ ## Integration with Architectural Decisions
1048
+
1049
+ Ensure all development guidance:
1050
+ - **Aligns with ADRs**: Every recommendation supports architectural decisions
1051
+ - **Maintains Consistency**: Consistent patterns across the codebase
1052
+ - **Enables Evolution**: Flexible design for future changes
1053
+ - **Supports Quality**: Built-in quality and maintainability
1054
+
1055
+ Make the guidance **actionable, specific, and immediately implementable** so developers can start coding with confidence and architectural alignment.
1056
+ `;
1057
+ // Execute the development guidance with AI if enabled
1058
+ const { executePromptWithFallback, formatMCPResponse } = await import('./utils/prompt-execution.js');
1059
+ const executionResult = await executePromptWithFallback(developmentPrompt, 'Analyze the development context and provide comprehensive implementation guidance that translates architectural decisions into specific coding tasks and development roadmap.', {
1060
+ temperature: 0.1,
1061
+ maxTokens: 8000,
1062
+ systemPrompt: `You are an expert software development advisor specializing in translating architectural decisions into practical implementation guidance.
1063
+ Your role is to bridge the gap between architectural planning and actual code development.
1064
+ Provide specific, actionable development guidance with clear implementation steps, code patterns, and quality criteria.
1065
+ Focus on practical guidance that ensures architectural decisions are properly implemented in code.
1066
+ Consider team context, technology stack, and development phase to provide tailored recommendations.`,
1067
+ });
1068
+ if (executionResult.isAIGenerated) {
1069
+ // AI execution successful - return actual development guidance
1070
+ return formatMCPResponse({
1071
+ ...executionResult,
1072
+ content: `# Development Guidance & Implementation Roadmap
1073
+
1074
+ ## Your Development Context
1075
+ - **Development Phase**: ${developmentPhase}
1076
+ - **Technology Stack**: ${technologyStack.length > 0 ? technologyStack.join(', ') : 'Not specified'}
1077
+ - **Current Progress**: ${currentProgress || 'Starting fresh'}
1078
+ - **Team Context**: ${teamContext.size} team with ${teamContext.experienceLevel} experience
1079
+ - **Timeline**: ${timeline || 'Not specified'}
1080
+ - **Focus Areas**: ${focusAreas.length > 0 ? focusAreas.join(', ') : 'General development'}
1081
+ - **ADRs to Implement**: ${adrsToImplement.length > 0 ? adrsToImplement.join(', ') : 'None specified'}
1082
+
1083
+ ## AI-Generated Development Guidance
1084
+
1085
+ ${executionResult.content}
1086
+
1087
+ ## Integration with Workflow Tools
1088
+
1089
+ This development guidance works seamlessly with other MCP tools:
1090
+
1091
+ ### **Workflow Integration**
1092
+ 1. **get_workflow_guidance** → Recommends architectural process
1093
+ 2. **get_development_guidance** → Guides implementation (this tool)
1094
+ 3. **validate_rules** → Ensures code follows architectural decisions
1095
+ 4. **analyze_deployment_progress** → Tracks implementation progress
1096
+
1097
+ ### **Quality Assurance Tools**
1098
+ - **generate_rules** → Extract coding standards from ADRs
1099
+ - **validate_rules** → Validate code against architectural rules
1100
+ - **analyze_content_security** → Security validation during development
1101
+
1102
+ ### **Documentation Tools**
1103
+ - **discover_existing_adrs** → Reference existing architectural decisions
1104
+
1105
+ ## Next Steps: From Architecture to Code
1106
+
1107
+ 1. **📋 Review the Development Roadmap** above
1108
+ 2. **🏗️ Set Up Project Structure** as recommended
1109
+ 3. **🧪 Implement Testing Strategy** early in development
1110
+ 4. **📊 Track Progress** using the success metrics provided
1111
+ 5. **🔄 Iterate and Refine** based on implementation learnings
1112
+
1113
+ This guidance ensures your development work is **architecturally aligned**, **quality-focused**, and **efficiently executed**!
1114
+ `,
1115
+ });
1116
+ }
1117
+ else {
1118
+ // Fallback to prompt-only mode
1119
+ return {
1120
+ content: [
1121
+ {
1122
+ type: 'text',
1123
+ text: developmentPrompt,
1124
+ },
1125
+ ],
1126
+ };
1127
+ }
1128
+ }
1129
+ catch (error) {
1130
+ throw new McpAdrError(`Failed to generate development guidance: ${error instanceof Error ? error.message : String(error)}`, 'DEVELOPMENT_ERROR');
1131
+ }
1132
+ }
1133
+ async analyzeProjectEcosystem(args, context) {
1134
+ const ctx = context || createNoOpContext();
1135
+ // Use configured project path if not provided in args
1136
+ const projectPath = args.projectPath || this.config.projectPath;
1137
+ const { includePatterns, enhancedMode = getEnhancedModeDefault(), // Environment-aware default
1138
+ knowledgeEnhancement = getKnowledgeEnhancementDefault(), // Environment-aware default
1139
+ learningEnabled = true, technologyFocus = [], analysisDepth = 'comprehensive', includeEnvironment = true, recursiveDepth = 'comprehensive', analysisScope = [],
1140
+ // conversationContext - TODO: implement context integration for ecosystem analysis
1141
+ } = args;
1142
+ this.logger.info(`Generating comprehensive ecosystem analysis for project at: ${projectPath}`);
1143
+ this.logger.info(`Analysis configuration - Depth: ${analysisDepth}, Recursive: ${recursiveDepth}, Environment: ${includeEnvironment}`);
1144
+ this.logger.info(`Enhancement features - Knowledge: ${knowledgeEnhancement}, Learning: ${learningEnabled}`);
1145
+ this.logger.info(`Analysis scope: ${analysisScope.length > 0 ? analysisScope.join(', ') : 'Full ecosystem analysis'}`);
1146
+ ctx.info(`🌐 Starting comprehensive ecosystem analysis: ${projectPath}`);
1147
+ ctx.report_progress(0, 100);
1148
+ try {
1149
+ ctx.info('📊 Phase 1: Analyzing project structure');
1150
+ ctx.report_progress(10, 100);
1151
+ // Import utilities dynamically to avoid circular dependencies
1152
+ const { analyzeProjectStructureCompat: analyzeProjectStructure } = await import('./utils/file-system.js');
1153
+ // Initialize ADR knowledge base on first run
1154
+ ctx.info('📚 Phase 1.5: Initializing ADR knowledge base');
1155
+ ctx.report_progress(15, 100);
1156
+ try {
1157
+ const { initializeAdrKnowledgeBase, isAdrKnowledgeBaseInitialized } = await import('./utils/adr-knowledge-initializer.js');
1158
+ const isInitialized = await isAdrKnowledgeBaseInitialized(this.kgManager);
1159
+ if (!isInitialized) {
1160
+ this.logger.info('First run detected - initializing ADR knowledge base');
1161
+ const initResult = await initializeAdrKnowledgeBase(this.kgManager, this.config.adrDirectory, projectPath);
1162
+ if (initResult.success) {
1163
+ this.logger.info(`✅ ADR knowledge base initialized with ${initResult.adrsIndexed} ADRs`);
1164
+ ctx.info(`📚 Indexed ${initResult.adrsIndexed} existing ADRs to knowledge base`);
1165
+ }
1166
+ else {
1167
+ this.logger.warn(`ADR knowledge base initialization completed with errors: ${initResult.errors.join(', ')}`);
1168
+ }
1169
+ }
1170
+ else {
1171
+ this.logger.info('ADR knowledge base already initialized - skipping');
1172
+ }
1173
+ }
1174
+ catch (error) {
1175
+ this.logger.warn('Failed to initialize ADR knowledge base:', error);
1176
+ // Don't fail the entire analysis if ADR initialization fails
1177
+ }
1178
+ // DEPRECATED: Legacy context assembly for enhanced mode
1179
+ // This section is part of the OpenRouter execution path and will be removed
1180
+ // in a future release. For CE-MCP mode, use createAnalyzeProjectEcosystemDirective()
1181
+ // from src/tools/ce-mcp-tools.ts instead. See ADR-014.
1182
+ let generateArchitecturalKnowledge = null;
1183
+ let executeWithReflexion = null;
1184
+ let retrieveRelevantMemories = null;
1185
+ let createToolReflexionConfig = null;
1186
+ if (enhancedMode) {
1187
+ if (knowledgeEnhancement) {
1188
+ const knowledgeModule = await import('./utils/knowledge-generation.js');
1189
+ generateArchitecturalKnowledge = knowledgeModule.generateArchitecturalKnowledge;
1190
+ }
1191
+ if (learningEnabled) {
1192
+ const reflexionModule = await import('./utils/reflexion.js');
1193
+ executeWithReflexion = reflexionModule.executeWithReflexion;
1194
+ retrieveRelevantMemories = reflexionModule.retrieveRelevantMemories;
1195
+ createToolReflexionConfig = reflexionModule.createToolReflexionConfig;
1196
+ }
1197
+ }
1198
+ // Step 1: Generate technology-specific knowledge if enabled
1199
+ ctx.info('🧠 Phase 2: Generating architectural knowledge');
1200
+ ctx.report_progress(25, 100);
1201
+ let knowledgeContext = '';
1202
+ if (enhancedMode && knowledgeEnhancement && generateArchitecturalKnowledge) {
1203
+ try {
1204
+ const knowledgeResult = await generateArchitecturalKnowledge({
1205
+ projectPath,
1206
+ technologies: technologyFocus,
1207
+ patterns: [],
1208
+ projectType: 'ecosystem-analysis',
1209
+ existingAdrs: [],
1210
+ }, {
1211
+ domains: this.getEcosystemAnalysisDomains(technologyFocus),
1212
+ depth: analysisDepth === 'basic' ? 'basic' : 'intermediate',
1213
+ cacheEnabled: true,
1214
+ });
1215
+ knowledgeContext = `
1216
+ ## Technology-Specific Knowledge Enhancement
1217
+
1218
+ The following architectural knowledge has been generated to enhance ecosystem analysis:
1219
+
1220
+ ${knowledgeResult.prompt}
1221
+
1222
+ ---
1223
+ `;
1224
+ }
1225
+ catch (error) {
1226
+ this.logger.warn('Knowledge generation failed:', error);
1227
+ knowledgeContext = '<!-- Knowledge generation unavailable -->\n';
1228
+ }
1229
+ }
1230
+ // Step 2: Retrieve relevant memories if learning is enabled
1231
+ let reflexionContext = '';
1232
+ if (enhancedMode && learningEnabled && retrieveRelevantMemories) {
1233
+ try {
1234
+ const memoryResult = await retrieveRelevantMemories('ecosystem-analysis', { projectPath, analysisDepth, technologyFocus }, { maxResults: 5, relevanceThreshold: 0.6 });
1235
+ reflexionContext = `
1236
+ ## Learning from Past Analyses
1237
+
1238
+ The following insights from past ecosystem analysis tasks will inform this analysis:
1239
+
1240
+ ${memoryResult.prompt}
1241
+
1242
+ ---
1243
+ `;
1244
+ }
1245
+ catch (error) {
1246
+ this.logger.warn('Reflexion memory retrieval failed:', error);
1247
+ reflexionContext = '<!-- Learning context unavailable -->\n';
1248
+ }
1249
+ }
1250
+ // Step 3: Generate base project analysis prompt with recursive depth
1251
+ ctx.info('📁 Phase 3: Scanning project files and structure');
1252
+ ctx.report_progress(40, 100);
1253
+ const baseProjectAnalysisPrompt = await analyzeProjectStructure(projectPath);
1254
+ // Step 4: Generate environment analysis if enabled
1255
+ ctx.info('🔧 Phase 4: Analyzing environment and infrastructure');
1256
+ ctx.report_progress(55, 100);
1257
+ let environmentAnalysisContext = '';
1258
+ if (includeEnvironment) {
1259
+ try {
1260
+ this.logger.info('Including comprehensive environment analysis in ecosystem analysis');
1261
+ const { analyzeEnvironment } = await import('./tools/environment-analysis-tool.js');
1262
+ // Call environment analysis with comprehensive scope
1263
+ const environmentResult = await analyzeEnvironment({
1264
+ projectPath,
1265
+ adrDirectory: this.config.adrDirectory,
1266
+ analysisType: 'comprehensive',
1267
+ });
1268
+ // Extract environment analysis content
1269
+ if (environmentResult.content && environmentResult.content[0]) {
1270
+ environmentAnalysisContext = `
1271
+ ## Integrated Environment Analysis
1272
+
1273
+ ${environmentResult.content[0].text}
1274
+
1275
+ ---
1276
+ `;
1277
+ }
1278
+ }
1279
+ catch (error) {
1280
+ this.logger.warn('Environment analysis integration failed:', error);
1281
+ environmentAnalysisContext = `
1282
+ ## Environment Analysis
1283
+ <!-- Environment analysis unavailable: ${error instanceof Error ? error.message : 'Unknown error'} -->
1284
+
1285
+ ---
1286
+ `;
1287
+ }
1288
+ }
1289
+ // Step 5: Apply Reflexion execution if learning is enabled
1290
+ ctx.info('🧪 Phase 5: Applying learning and reflexion');
1291
+ ctx.report_progress(70, 100);
1292
+ let enhancedAnalysisPrompt = baseProjectAnalysisPrompt.prompt + environmentAnalysisContext;
1293
+ if (enhancedMode && learningEnabled && executeWithReflexion && createToolReflexionConfig) {
1294
+ try {
1295
+ const reflexionConfig = createToolReflexionConfig('analyze_project_ecosystem', {
1296
+ reflectionDepth: analysisDepth === 'basic' ? 'basic' : 'detailed',
1297
+ evaluationCriteria: ['task-success', 'accuracy', 'completeness'],
1298
+ learningRate: 0.7,
1299
+ });
1300
+ const reflexionResult = await executeWithReflexion({
1301
+ prompt: baseProjectAnalysisPrompt.prompt + knowledgeContext + environmentAnalysisContext,
1302
+ instructions: baseProjectAnalysisPrompt.instructions,
1303
+ context: {
1304
+ projectPath,
1305
+ analysisDepth,
1306
+ recursiveDepth,
1307
+ technologyFocus,
1308
+ includePatterns,
1309
+ includeEnvironment,
1310
+ analysisScope,
1311
+ knowledgeEnhanced: knowledgeEnhancement,
1312
+ learningEnabled: true,
1313
+ },
1314
+ }, reflexionConfig);
1315
+ enhancedAnalysisPrompt = reflexionResult.prompt;
1316
+ }
1317
+ catch (error) {
1318
+ this.logger.warn('Reflexion execution failed:', error);
1319
+ enhancedAnalysisPrompt =
1320
+ baseProjectAnalysisPrompt.prompt + knowledgeContext + environmentAnalysisContext;
1321
+ }
1322
+ }
1323
+ else {
1324
+ enhancedAnalysisPrompt =
1325
+ baseProjectAnalysisPrompt.prompt + knowledgeContext + environmentAnalysisContext;
1326
+ }
1327
+ // Execute the analysis with AI if enabled, otherwise return prompt
1328
+ ctx.info('🤖 Phase 6: Executing AI-powered ecosystem analysis');
1329
+ ctx.report_progress(85, 100);
1330
+ const { executeEcosystemAnalysisPrompt, formatMCPResponse } = await import('./utils/prompt-execution.js');
1331
+ const executionResult = await executeEcosystemAnalysisPrompt(enhancedAnalysisPrompt, baseProjectAnalysisPrompt.instructions, {
1332
+ temperature: 0.1,
1333
+ maxTokens: 6000,
1334
+ });
1335
+ // Step 6: Record project structure to knowledge graph
1336
+ try {
1337
+ this.logger.info('Recording project structure to knowledge graph');
1338
+ const projectStructureSnapshot = {
1339
+ projectPath,
1340
+ analysisDepth,
1341
+ recursiveDepth,
1342
+ technologyFocus,
1343
+ analysisScope,
1344
+ includeEnvironment,
1345
+ timestamp: new Date().toISOString(),
1346
+ structureData: baseProjectAnalysisPrompt.context || {},
1347
+ };
1348
+ await this.kgManager.recordProjectStructure(projectStructureSnapshot);
1349
+ this.logger.info('✅ Project structure recorded to knowledge graph');
1350
+ }
1351
+ catch (kgError) {
1352
+ this.logger.warn('Failed to record project structure to knowledge graph:', kgError);
1353
+ // Don't fail the entire analysis if KG recording fails
1354
+ }
1355
+ ctx.info('✅ Ecosystem analysis completed successfully');
1356
+ ctx.report_progress(100, 100);
1357
+ // Return appropriate response based on execution result
1358
+ if (executionResult.isAIGenerated) {
1359
+ // AI execution successful - return actual analysis results
1360
+ return formatMCPResponse({
1361
+ ...executionResult,
1362
+ content: `# Comprehensive Project Ecosystem Analysis Results
1363
+
1364
+ ## Analysis Configuration
1365
+ - **Project Path**: ${projectPath}
1366
+ - **Analysis Depth**: ${analysisDepth}
1367
+ - **Recursive Depth**: ${recursiveDepth}
1368
+ - **Environment Analysis**: ${includeEnvironment ? '✅ Included' : '❌ Excluded'}
1369
+ - **Analysis Scope**: ${analysisScope.length > 0 ? analysisScope.join(', ') : 'Full ecosystem analysis'}
1370
+
1371
+ ## Enhancement Features
1372
+ - **Knowledge Generation**: ${enhancedMode && knowledgeEnhancement ? '✅ Enabled' : '❌ Disabled'}
1373
+ - **Reflexion Learning**: ${enhancedMode && learningEnabled ? '✅ Enabled' : '❌ Disabled'}
1374
+ - **Enhanced Mode**: ${enhancedMode ? '✅ Enabled' : '❌ Disabled'}
1375
+ - **Technology Focus**: ${technologyFocus.length > 0 ? technologyFocus.join(', ') : 'Auto-detect'}
1376
+ - **Knowledge Graph**: ✅ Project structure recorded
1377
+
1378
+ ${knowledgeContext}
1379
+
1380
+ ${reflexionContext}
1381
+
1382
+ ## Comprehensive Ecosystem Analysis Results
1383
+
1384
+ ${executionResult.content}
1385
+
1386
+ ${includeEnvironment
1387
+ ? `
1388
+
1389
+ ## Environment Integration Summary
1390
+
1391
+ The analysis above includes comprehensive environment analysis covering:
1392
+ - **Infrastructure Specifications**: Deployment and runtime environment details
1393
+ - **Containerization**: Docker, Kubernetes, and container orchestration analysis
1394
+ - **Environment Requirements**: Configuration and dependency requirements
1395
+ - **Compliance Assessment**: Security and regulatory compliance evaluation
1396
+
1397
+ This integrated approach provides complete understanding of both codebase patterns AND operational environment.
1398
+ `
1399
+ : ''}
1400
+
1401
+ ## Next Steps: Complete Ecosystem Understanding
1402
+
1403
+ Based on the comprehensive analysis above:
1404
+
1405
+ ### **Immediate Actions**
1406
+ 1. **Review Ecosystem Overview**: Examine the complete technology stack and environment context
1407
+ 2. **Assess Integration Points**: Understand how code patterns relate to operational environment
1408
+ 3. **Identify Critical Dependencies**: Focus on key dependencies between code and infrastructure
1409
+
1410
+ ### **Strategic Planning**
1411
+ 4. **Address Architectural Issues**: Prioritize improvements based on both code and environment analysis
1412
+ 5. **Plan Environment Optimization**: Optimize deployment and operational configurations
1413
+ 6. **Update Documentation**: Document both architectural decisions and environment specifications
1414
+
1415
+ ### **Implementation Roadmap**
1416
+ 7. **Implement Code Improvements**: Execute code-level architectural enhancements
1417
+ 8. **Optimize Environment**: Improve infrastructure and deployment configurations
1418
+ 9. **Monitor Integration**: Ensure code and environment changes work together effectively
1419
+
1420
+ This comprehensive ecosystem analysis provides the foundation for informed architectural and operational decisions.
1421
+ `,
1422
+ });
1423
+ }
1424
+ else {
1425
+ // Fallback to prompt-only mode
1426
+ return {
1427
+ content: [
1428
+ {
1429
+ type: 'text',
1430
+ text: `# Comprehensive Project Ecosystem Analysis
1431
+
1432
+ This comprehensive analysis provides deep recursive project understanding with integrated environment analysis.
1433
+
1434
+ ## Analysis Configuration
1435
+ - **Project Path**: ${projectPath}
1436
+ - **Analysis Depth**: ${analysisDepth}
1437
+ - **Recursive Depth**: ${recursiveDepth}
1438
+ - **Environment Analysis**: ${includeEnvironment ? '✅ Included' : '❌ Excluded'}
1439
+ - **Analysis Scope**: ${analysisScope.length > 0 ? analysisScope.join(', ') : 'Full ecosystem analysis'}
1440
+
1441
+ ## Enhancement Features
1442
+ - **Knowledge Generation**: ${enhancedMode && knowledgeEnhancement ? '✅ Enabled' : '❌ Disabled'}
1443
+ - **Reflexion Learning**: ${enhancedMode && learningEnabled ? '✅ Enabled' : '❌ Disabled'}
1444
+ - **Enhanced Mode**: ${enhancedMode ? '✅ Enabled' : '❌ Disabled'}
1445
+ - **Technology Focus**: ${technologyFocus.length > 0 ? technologyFocus.join(', ') : 'Auto-detect'}
1446
+ - **Include Patterns**: ${includePatterns?.length ? includePatterns.join(', ') : 'Default patterns'}
1447
+ - **Knowledge Graph**: ✅ Project structure recorded
1448
+
1449
+ ${knowledgeContext}
1450
+
1451
+ ${reflexionContext}
1452
+
1453
+ ## Enhanced Analysis Prompt
1454
+
1455
+ ${enhancedAnalysisPrompt}
1456
+
1457
+ ## Enhanced Implementation Instructions
1458
+
1459
+ ${baseProjectAnalysisPrompt.instructions}
1460
+
1461
+ ### Enhancement-Specific Instructions
1462
+
1463
+ ${enhancedMode && knowledgeEnhancement
1464
+ ? `
1465
+ #### Knowledge Enhancement
1466
+ - Apply technology-specific knowledge to ecosystem analysis
1467
+ - Use domain expertise to identify patterns and anti-patterns
1468
+ - Leverage architectural best practices for technology stack evaluation
1469
+ `
1470
+ : ''}
1471
+
1472
+ ${enhancedMode && learningEnabled
1473
+ ? `
1474
+ #### Learning Integration
1475
+ - Apply lessons learned from past ecosystem analyses
1476
+ - Use memory insights to improve pattern recognition accuracy
1477
+ - Incorporate feedback from previous analysis outcomes
1478
+ `
1479
+ : ''}
1480
+
1481
+ ## Expected Enhanced Output
1482
+
1483
+ The enhanced analysis should provide:
1484
+ 1. **Technology Stack Analysis** with domain knowledge context
1485
+ 2. **Architectural Pattern Detection** informed by past experiences
1486
+ 3. **Ecosystem Health Assessment** using learned evaluation criteria
1487
+ 4. **Improvement Recommendations** based on domain best practices
1488
+ 5. **Learning Insights** for future analysis improvement
1489
+
1490
+ ## Quality Assurance
1491
+
1492
+ - Ensure analysis leverages all available enhancement features
1493
+ - Verify technology-specific knowledge is properly applied
1494
+ - Confirm learning insights improve analysis accuracy
1495
+ - Validate recommendations align with domain best practices`,
1496
+ },
1497
+ ],
1498
+ };
1499
+ }
1500
+ }
1501
+ catch (error) {
1502
+ throw new McpAdrError(`Failed to analyze project ecosystem: ${error instanceof Error ? error.message : String(error)}`, 'ANALYSIS_ERROR');
1503
+ }
1504
+ }
1505
+ async getArchitecturalContext(args) {
1506
+ const { filePath, includeCompliance = true } = args;
1507
+ try {
1508
+ const { analyzeProjectStructureCompat: analyzeProjectStructure, fileExistsCompat: fileExists, ensureDirectoryCompat: ensureDirectory, } = await import('./utils/file-system.js');
1509
+ const path = await import('path');
1510
+ // Determine project path
1511
+ const projectPath = filePath
1512
+ ? filePath.split('/').slice(0, -1).join('/')
1513
+ : this.config.projectPath;
1514
+ const adrDirectory = path.join(projectPath, this.config.adrDirectory);
1515
+ // Generate prompts for ADR directory setup
1516
+ const adrDirectoryCheckPrompt = await fileExists(adrDirectory);
1517
+ const adrDirectorySetupPrompt = await ensureDirectory(adrDirectory);
1518
+ // Generate architectural analysis prompt
1519
+ const projectAnalysisPrompt = await analyzeProjectStructure(projectPath);
1520
+ const architecturalPrompt = `
1521
+ # Architectural Context Analysis & Project Setup
1522
+
1523
+ ## Project Overview
1524
+ **Project Path**: ${projectPath}
1525
+ **Analysis Scope**: ${filePath ? `Specific file: ${filePath}` : 'Entire project'}
1526
+ **ADR Directory**: ${this.config.adrDirectory}
1527
+ **Include Compliance**: ${includeCompliance ? 'Yes' : 'No'}
1528
+
1529
+ ## 🚀 ADR Infrastructure Setup
1530
+
1531
+ This analysis will include setting up ADR infrastructure if needed:
1532
+
1533
+ ### ADR Directory Check
1534
+ ${adrDirectoryCheckPrompt.prompt}
1535
+
1536
+ ### ADR Directory Setup (if needed)
1537
+ ${adrDirectorySetupPrompt.prompt}
1538
+
1539
+ ## Comprehensive Project Analysis
1540
+
1541
+ ${projectAnalysisPrompt.prompt}
1542
+
1543
+ ## Enhanced Architectural Focus
1544
+
1545
+ Please provide a **comprehensive, outcome-focused analysis** including:
1546
+
1547
+ ### 1. Technology Stack & Infrastructure Analysis
1548
+ - **Core Technologies**: Programming languages, frameworks, runtime environments
1549
+ - **Dependencies**: Package managers, third-party libraries, version constraints
1550
+ - **Build & Deployment**: CI/CD pipelines, build tools, deployment strategies
1551
+ - **Data Layer**: Databases, caching, data storage and retrieval patterns
1552
+
1553
+ ### 2. Architectural Pattern & Design Analysis
1554
+ - **System Architecture**: Monolith, microservices, serverless, hybrid patterns
1555
+ - **Code Organization**: Module structure, separation of concerns, layering
1556
+ - **API Design**: REST, GraphQL, RPC patterns and conventions
1557
+ - **Data Flow**: Request/response cycles, event handling, state management
1558
+ ${filePath ? `- **File-specific Context**: How ${filePath} fits into the overall architecture` : ''}
1559
+
1560
+ ### 3. Quality, Security & Performance Assessment
1561
+ - **Code Quality**: Structure, naming, documentation, testing strategies
1562
+ - **Security Implementation**: Authentication, authorization, data protection
1563
+ - **Performance Patterns**: Caching, optimization, scalability considerations
1564
+ - **Monitoring & Observability**: Logging, metrics, error tracking
1565
+
1566
+ ### 4. Architectural Decision Discovery & Documentation
1567
+ - **Explicit Decisions**: Find existing documentation and decision records
1568
+ - **Implicit Decisions**: Identify significant undocumented architectural choices
1569
+ - **Technology Rationale**: Understand selection criteria and trade-offs
1570
+ - **Evolution Path**: How the architecture has changed over time
1571
+
1572
+ ${includeCompliance
1573
+ ? `### 5. Compliance & Standards Assessment
1574
+ - **Industry Standards**: Adherence to relevant industry standards and best practices
1575
+ - **Security Compliance**: Security standards compliance (OWASP, SOC2, etc.)
1576
+ - **Code Standards**: Coding standards and style guide compliance
1577
+ - **Architectural Compliance**: Adherence to established architectural principles
1578
+ - **Regulatory Requirements**: Any regulatory compliance requirements (GDPR, HIPAA, etc.)`
1579
+ : ''}
1580
+
1581
+ ## Expected Output: Outcome-Focused Architectural Context
1582
+
1583
+ Provide a **comprehensive architectural context** with **clear project outcomes**:
1584
+
1585
+ ### 📋 **1. Executive Summary & Project Outcomes**
1586
+ - **Current State**: What the project is and what it does
1587
+ - **Architectural Maturity**: Assessment of current architectural practices
1588
+ - **Key Strengths**: What's working well architecturally
1589
+ - **Critical Gaps**: What needs immediate attention
1590
+ - **Success Metrics**: How to measure architectural improvements
1591
+
1592
+ ### 🔧 **2. Technology & Infrastructure Inventory**
1593
+ - **Technology Stack**: Complete inventory with versions and purposes
1594
+ - **Infrastructure Components**: Deployment, monitoring, data storage
1595
+ - **Dependencies**: Critical dependencies and potential risks
1596
+ - **Tool Chain**: Development, testing, and deployment tools
1597
+
1598
+ ### 🏗️ **3. Architectural Patterns & Design Decisions**
1599
+ - **System Design**: Overall architectural approach and patterns
1600
+ - **Component Architecture**: How major components interact
1601
+ - **Data Architecture**: How data flows and is managed
1602
+ - **Integration Patterns**: How external systems are integrated
1603
+
1604
+ ### 📊 **4. Quality & Compliance Assessment**
1605
+ - **Code Quality Score**: Assessment of current code quality
1606
+ - **Security Posture**: Security implementation and gaps
1607
+ - **Performance Profile**: Current performance characteristics
1608
+ - **Maintainability Index**: How easy the system is to maintain and evolve
1609
+
1610
+ ### 🎯 **5. Outcome-Focused Action Plan**
1611
+ Based on the analysis, provide a **clear workflow** with **projected outcomes**:
1612
+
1613
+ #### **Immediate Actions (Next 1-2 weeks)**
1614
+ - **Priority 1**: Most critical architectural issues to address
1615
+ - **Quick Wins**: Low-effort, high-impact improvements
1616
+ - **Documentation**: Essential decisions that need immediate documentation
1617
+
1618
+ #### **Short-term Goals (Next 1-3 months)**
1619
+ - **Architectural Improvements**: Planned enhancements with expected outcomes
1620
+ - **Technical Debt**: Priority technical debt to address
1621
+ - **Process Improvements**: Development workflow enhancements
1622
+
1623
+ #### **Long-term Vision (3-12 months)**
1624
+ - **Strategic Architecture**: Long-term architectural evolution
1625
+ - **Scalability Roadmap**: How to scale the system effectively
1626
+ - **Innovation Opportunities**: Areas for architectural innovation
1627
+
1628
+ ### 📈 **6. Success Metrics & Outcomes**
1629
+ Define **measurable outcomes** for architectural improvements:
1630
+
1631
+ - **Performance Metrics**: Response times, throughput, resource utilization
1632
+ - **Quality Metrics**: Code coverage, bug rates, maintainability scores
1633
+ - **Developer Experience**: Build times, deployment frequency, developer satisfaction
1634
+ - **Business Impact**: Feature delivery speed, system reliability, cost efficiency
1635
+
1636
+ ### 🏗️ **7. ADR Infrastructure & Documentation Plan**
1637
+
1638
+ If ADR directory doesn't exist, also provide:
1639
+
1640
+ 1. **Create Directory Structure**:
1641
+ \`\`\`
1642
+ ${this.config.adrDirectory}/
1643
+ ├── 0001-record-architecture-decisions.md (template)
1644
+ ├── README.md (ADR process guide)
1645
+ └── template.md (ADR template)
1646
+ \`\`\`
1647
+
1648
+ 2. **Generate Initial ADRs** for discovered architectural decisions
1649
+ 3. **Create ADR Process Guide** for the team
1650
+ 4. **Establish ADR Workflow** for future decisions
1651
+
1652
+ ### 🔄 **8. Continuous Improvement Workflow**
1653
+ Establish ongoing architectural governance:
1654
+
1655
+ - **Regular Reviews**: Monthly architectural health checks
1656
+ - **Decision Documentation**: Process for documenting new architectural decisions
1657
+ - **Compliance Monitoring**: Ongoing adherence to architectural standards
1658
+ - **Evolution Planning**: Quarterly architectural roadmap updates
1659
+
1660
+ ## Next Steps: Grounded Project Workflow
1661
+
1662
+ After this analysis, follow this **outcome-focused workflow**:
1663
+
1664
+ 1. **📋 Review Analysis**: Examine the architectural context and recommendations
1665
+ 2. **🎯 Set Priorities**: Choose 3-5 most impactful improvements based on outcomes
1666
+ 3. **📝 Document Decisions**: Create ADRs for significant architectural choices
1667
+ 4. **🔧 Implement Changes**: Execute improvements in priority order
1668
+ 5. **📊 Measure Progress**: Track success metrics and outcomes
1669
+ 6. **🔄 Iterate**: Regular reviews and continuous improvement
1670
+
1671
+ This approach ensures that architectural work is **grounded in measurable outcomes** and **aligned with project success**.
1672
+ `;
1673
+ // Execute the analysis with AI if enabled, otherwise return prompt
1674
+ const { executeEcosystemAnalysisPrompt, formatMCPResponse } = await import('./utils/prompt-execution.js');
1675
+ const executionResult = await executeEcosystemAnalysisPrompt(architecturalPrompt, projectAnalysisPrompt.instructions, {
1676
+ temperature: 0.1,
1677
+ maxTokens: 5000,
1678
+ systemPrompt: `You are a senior software architect specializing in architectural context analysis.
1679
+ Analyze the provided project to understand its architectural patterns, design decisions, and structural organization.
1680
+ Focus on providing actionable insights about the architecture that can guide development decisions.`,
1681
+ });
1682
+ if (executionResult.isAIGenerated) {
1683
+ // AI execution successful - return actual analysis results
1684
+ return formatMCPResponse({
1685
+ ...executionResult,
1686
+ content: `# Architectural Context Analysis Results
1687
+
1688
+ ${filePath ? `## Target File: ${filePath}` : '## Project-wide Analysis'}
1689
+
1690
+ ## Project Information
1691
+ - **Project Path**: ${projectPath}
1692
+ - **Analysis Scope**: ${filePath ? 'File-specific' : 'Project-wide'}
1693
+ - **ADR Directory**: ${this.config.adrDirectory}
1694
+
1695
+ ## ADR Infrastructure Setup
1696
+
1697
+ The analysis includes automatic ADR infrastructure setup:
1698
+
1699
+ ${adrDirectoryCheckPrompt.instructions}
1700
+
1701
+ ${adrDirectorySetupPrompt.instructions}
1702
+
1703
+ ## AI Analysis Results
1704
+
1705
+ ${executionResult.content}
1706
+
1707
+ ## Outcome-Focused Next Steps
1708
+
1709
+ Based on the architectural analysis, follow this **grounded workflow**:
1710
+
1711
+ ### **Immediate Actions (This Week)**
1712
+ 1. **Review Analysis**: Examine the architectural context and recommendations above
1713
+ 2. **Set Up ADRs**: Ensure ADR directory structure is created and ready
1714
+ 3. **Identify Quick Wins**: Focus on low-effort, high-impact improvements
1715
+
1716
+ ### **Short-term Goals (Next Month)**
1717
+ 4. **Document Key Decisions**: Create ADRs for the most significant architectural choices
1718
+ 5. **Address Critical Issues**: Tackle the highest-priority architectural concerns
1719
+ 6. **Establish Metrics**: Set up measurement for the success metrics identified
1720
+
1721
+ ### **Long-term Vision (Next Quarter)**
1722
+ 7. **Implement Roadmap**: Execute the architectural improvement plan
1723
+ 8. **Monitor Progress**: Track success metrics and adjust approach as needed
1724
+ 9. **Continuous Improvement**: Establish regular architectural reviews
1725
+
1726
+ This **outcome-focused approach** ensures architectural work delivers **measurable value** and keeps the project **grounded in clear objectives**.
1727
+ `,
1728
+ });
1729
+ }
1730
+ else {
1731
+ // Fallback to prompt-only mode
1732
+ return {
1733
+ content: [
1734
+ {
1735
+ type: 'text',
1736
+ text: architecturalPrompt,
1737
+ },
1738
+ ],
1739
+ };
1740
+ }
1741
+ }
1742
+ catch (error) {
1743
+ throw new McpAdrError(`Failed to get architectural context: ${error instanceof Error ? error.message : String(error)}`, 'ANALYSIS_ERROR');
1744
+ }
1745
+ }
1746
+ async generateAdrsFromPrd(args, context) {
1747
+ const ctx = context || createNoOpContext();
1748
+ const { prdPath, enhancedMode = getEnhancedModeDefault(), // Environment-aware default
1749
+ promptOptimization = true, knowledgeEnhancement = getKnowledgeEnhancementDefault(), // Environment-aware default
1750
+ prdType = 'general', } = args;
1751
+ const outputDirectory = args['outputDirectory'] || this.config.adrDirectory;
1752
+ this.logger.info(`Generating enhanced ADRs from PRD: ${prdPath} to ${outputDirectory}`);
1753
+ this.logger.info(`Enhancement features - APE: ${promptOptimization}, Knowledge: ${knowledgeEnhancement}, Type: ${prdType}`);
1754
+ ctx.info(`📝 Starting ADR generation from PRD: ${prdPath}`);
1755
+ ctx.report_progress(0, 100);
1756
+ try {
1757
+ ctx.info('📂 Phase 1: Validating PRD file');
1758
+ ctx.report_progress(10, 100);
1759
+ const { readFileContentCompat: readFileContent, fileExistsCompat: fileExists } = await import('./utils/file-system.js');
1760
+ // Import advanced prompting utilities if enhanced mode is enabled
1761
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
1762
+ let generateArchitecturalKnowledge = null;
1763
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
1764
+ let optimizePromptWithAPE = null;
1765
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
1766
+ let createToolAPEConfig = null;
1767
+ if (enhancedMode) {
1768
+ if (knowledgeEnhancement) {
1769
+ const knowledgeModule = await import('./utils/knowledge-generation.js');
1770
+ generateArchitecturalKnowledge = knowledgeModule.generateArchitecturalKnowledge;
1771
+ }
1772
+ if (promptOptimization) {
1773
+ const apeModule = await import('./utils/automatic-prompt-engineering.js');
1774
+ optimizePromptWithAPE = apeModule.optimizePromptWithAPE;
1775
+ createToolAPEConfig = apeModule.createToolAPEConfig;
1776
+ }
1777
+ }
1778
+ // Generate file existence check prompt
1779
+ const fileExistsPrompt = await fileExists(prdPath);
1780
+ // Generate file content reading prompt
1781
+ const fileContentPrompt = await readFileContent(prdPath);
1782
+ ctx.info('📚 Phase 2: Reading PRD content');
1783
+ ctx.report_progress(25, 100);
1784
+ // Step 1: Generate domain-specific knowledge if enabled
1785
+ ctx.info('🧠 Phase 3: Generating domain knowledge');
1786
+ ctx.report_progress(40, 100);
1787
+ let knowledgeContext = '';
1788
+ if (enhancedMode && knowledgeEnhancement && generateArchitecturalKnowledge) {
1789
+ try {
1790
+ const knowledgeResult = await generateArchitecturalKnowledge({
1791
+ projectPath: outputDirectory,
1792
+ technologies: [],
1793
+ patterns: [],
1794
+ projectType: prdType,
1795
+ existingAdrs: [],
1796
+ }, {
1797
+ domains: this.getPrdTypeDomains(prdType),
1798
+ depth: 'intermediate',
1799
+ cacheEnabled: true,
1800
+ });
1801
+ knowledgeContext = `
1802
+ ## Domain-Specific Knowledge Enhancement
1803
+
1804
+ The following architectural knowledge has been generated to enhance PRD analysis and ADR creation:
1805
+
1806
+ ${knowledgeResult.prompt}
1807
+
1808
+ ---
1809
+ `;
1810
+ }
1811
+ catch (error) {
1812
+ this.logger.warn('Knowledge generation failed:', error);
1813
+ knowledgeContext = '<!-- Knowledge generation unavailable -->\n';
1814
+ }
1815
+ }
1816
+ // Step 2: Create base ADR generation prompt
1817
+ ctx.info('📋 Phase 4: Creating base ADR prompts');
1818
+ ctx.report_progress(60, 100);
1819
+ const baseAdrPrompt = this.createBaseAdrPrompt(prdPath, outputDirectory, knowledgeContext);
1820
+ // Step 3: Apply APE optimization if enabled
1821
+ ctx.info('⚡ Phase 5: Optimizing prompts with APE');
1822
+ ctx.report_progress(75, 100);
1823
+ let finalAdrPrompt = baseAdrPrompt;
1824
+ if (enhancedMode && promptOptimization && optimizePromptWithAPE && createToolAPEConfig) {
1825
+ try {
1826
+ const apeConfig = createToolAPEConfig('generate_adrs_from_prd', {
1827
+ candidateCount: 5,
1828
+ evaluationCriteria: ['task-completion', 'clarity', 'specificity'],
1829
+ optimizationRounds: 2,
1830
+ qualityThreshold: 0.75,
1831
+ });
1832
+ const apeResult = await optimizePromptWithAPE({
1833
+ prompt: baseAdrPrompt,
1834
+ instructions: 'Generate comprehensive ADRs from PRD analysis',
1835
+ context: {
1836
+ prdPath,
1837
+ outputDirectory,
1838
+ prdType,
1839
+ knowledgeEnhanced: knowledgeEnhancement,
1840
+ },
1841
+ }, apeConfig);
1842
+ finalAdrPrompt = apeResult.prompt;
1843
+ }
1844
+ catch (error) {
1845
+ this.logger.warn('APE optimization failed:', error);
1846
+ finalAdrPrompt = baseAdrPrompt;
1847
+ }
1848
+ }
1849
+ // Generate comprehensive ADR creation prompt that includes file operations
1850
+ const adrPrompt = `
1851
+ # Enhanced ADR Generation from PRD Request
1852
+
1853
+ This is a comprehensive prompt-driven ADR generation process enhanced with advanced prompting techniques.
1854
+
1855
+ ## Enhancement Status
1856
+ - **APE Optimization**: ${enhancedMode && promptOptimization ? '✅ Enabled' : '❌ Disabled'}
1857
+ - **Knowledge Generation**: ${enhancedMode && knowledgeEnhancement ? '✅ Enabled' : '❌ Disabled'}
1858
+ - **PRD Type**: ${prdType}
1859
+ - **Enhanced Mode**: ${enhancedMode ? '✅ Enabled' : '❌ Disabled'}
1860
+
1861
+ ## Step 1: File Validation
1862
+ ${fileExistsPrompt.prompt}
1863
+
1864
+ **Instructions**: First, execute the file existence check above. If the file does not exist, stop the process and report the error. Only proceed to Step 2 if the file exists.
1865
+
1866
+ ## Step 2: PRD Content Reading
1867
+ ${fileContentPrompt.prompt}
1868
+
1869
+ **Instructions**: Execute the file reading operation above to obtain the PRD content. Use the content from this step for the enhanced ADR generation in Step 3.
1870
+
1871
+ ## Step 3: Enhanced ADR Generation
1872
+
1873
+ ${enhancedMode && promptOptimization
1874
+ ? `
1875
+ ### APE-Optimized Analysis
1876
+ This prompt has been optimized using Automatic Prompt Engineering for superior ADR generation quality.
1877
+ The optimization focused on task completion, clarity, and specificity for PRD analysis.
1878
+
1879
+ `
1880
+ : ''}
1881
+
1882
+ ${finalAdrPrompt}
1883
+
1884
+ ### File Creation Instructions
1885
+
1886
+ For each generated ADR, create a file creation prompt using the following pattern:
1887
+ - **File Path**: ${outputDirectory}/[number]-[decision-title].md
1888
+ - **Content**: The complete enhanced ADR markdown content
1889
+ - **Action Confirmation**: Require user confirmation before creating files
1890
+ - **Security Validation**: Ensure output directory is safe and authorized
1891
+
1892
+ ### Enhanced Quality Assurance
1893
+
1894
+ - Ensure each ADR leverages domain knowledge when available
1895
+ - Verify decisions align with PRD type best practices
1896
+ - Check that enhancement features are properly utilized
1897
+ - Validate that ADR content exceeds baseline quality expectations
1898
+ - Confirm all decisions are traceable back to PRD requirements with domain context
1899
+ `;
1900
+ // Execute the ADR generation with AI if enabled, otherwise return prompt
1901
+ ctx.info('🤖 Phase 6: Executing AI-powered ADR generation');
1902
+ ctx.report_progress(90, 100);
1903
+ const { executeADRGenerationPrompt, formatMCPResponse } = await import('./utils/prompt-execution.js');
1904
+ const executionResult = await executeADRGenerationPrompt(adrPrompt, 'Generate comprehensive ADRs from PRD analysis with enhanced domain knowledge and optimization', {
1905
+ temperature: 0.1,
1906
+ maxTokens: 8000,
1907
+ systemPrompt: `You are an expert software architect who creates comprehensive Architectural Decision Records (ADRs) from Product Requirements Documents (PRDs).
1908
+ Generate well-structured ADRs that follow best practices and include all necessary sections.
1909
+ Focus on extracting architectural decisions from the PRD and creating actionable ADRs with clear reasoning.`,
1910
+ });
1911
+ ctx.info('✅ ADR generation completed successfully');
1912
+ ctx.report_progress(100, 100);
1913
+ if (executionResult.isAIGenerated) {
1914
+ // AI execution successful - return actual ADR generation results
1915
+ return formatMCPResponse({
1916
+ ...executionResult,
1917
+ content: `# ADR Generation from PRD Results
1918
+
1919
+ ## Enhancement Features
1920
+ - **APE Optimization**: ${enhancedMode && promptOptimization ? '✅ Enabled' : '❌ Disabled'}
1921
+ - **Knowledge Generation**: ${enhancedMode && knowledgeEnhancement ? '✅ Enabled' : '❌ Disabled'}
1922
+ - **PRD Type Optimization**: ${prdType}
1923
+ - **Enhanced Mode**: ${enhancedMode ? '✅ Enabled' : '❌ Disabled'}
1924
+
1925
+ ## Source Information
1926
+ - **PRD Path**: ${prdPath}
1927
+ - **Output Directory**: ${outputDirectory}
1928
+
1929
+ ## Generated ADRs
1930
+
1931
+ ${executionResult.content}
1932
+
1933
+ ## Next Steps
1934
+
1935
+ 1. **Review Generated ADRs**: Examine each ADR for completeness and accuracy
1936
+ 2. **Save ADR Files**: Create individual .md files for each ADR in ${outputDirectory}
1937
+ 3. **Update ADR Index**: Add new ADRs to your project's ADR catalog
1938
+ 4. **Stakeholder Review**: Share ADRs with team for feedback and approval
1939
+ 5. **Implementation Planning**: Create tasks for implementing the architectural decisions
1940
+
1941
+ ## File Creation Commands
1942
+
1943
+ To save the generated ADRs, create individual files in ${outputDirectory}:
1944
+
1945
+ \`\`\`bash
1946
+ # Create ADR directory if it doesn't exist
1947
+ mkdir -p ${outputDirectory}
1948
+
1949
+ # Save each ADR as a separate file (example)
1950
+ # Replace [NUMBER] and [TITLE] with actual values from generated ADRs
1951
+ # cat > "${outputDirectory}/001-example-decision.md" << 'EOF'
1952
+ # [ADR content here]
1953
+ # EOF
1954
+ \`\`\`
1955
+ `,
1956
+ });
1957
+ }
1958
+ else {
1959
+ // Fallback to prompt-only mode
1960
+ return {
1961
+ content: [
1962
+ {
1963
+ type: 'text',
1964
+ text: `# Enhanced ADR Generation from PRD: ${prdPath}
1965
+
1966
+ ## Advanced Prompt-Driven ADR Generation Process
1967
+
1968
+ This tool uses a 100% prompt-driven architecture enhanced with advanced prompting techniques:
1969
+
1970
+ ### Enhancement Features
1971
+ - **APE Optimization**: ${enhancedMode && promptOptimization ? '✅ Enabled - Prompts optimized for superior quality' : '❌ Disabled'}
1972
+ - **Knowledge Generation**: ${enhancedMode && knowledgeEnhancement ? '✅ Enabled - Domain knowledge enhanced analysis' : '❌ Disabled'}
1973
+ - **PRD Type Optimization**: ${prdType} - Tailored for specific domain requirements
1974
+ - **Enhanced Mode**: ${enhancedMode ? '✅ Enabled - All advanced features active' : '❌ Disabled - Basic mode'}
1975
+
1976
+ ### Enhanced AI Agent Workflow
1977
+
1978
+ 1. **Validate PRD file existence** using secure file system operations
1979
+ 2. **Read PRD content** safely with proper security validation
1980
+ 3. **Apply domain knowledge** to enhance understanding (if enabled)
1981
+ 4. **Generate optimized ADRs** using APE-enhanced prompts (if enabled)
1982
+ 5. **Create enhanced ADR files** in the specified output directory: ${outputDirectory}
1983
+
1984
+ ## Execution Instructions
1985
+
1986
+ Please execute the following enhanced comprehensive prompt:
1987
+
1988
+ ${adrPrompt}
1989
+
1990
+ ## Advanced Features
1991
+
1992
+ ${enhancedMode && knowledgeEnhancement
1993
+ ? `
1994
+ ### Knowledge Enhancement
1995
+ - Domain-specific architectural knowledge has been generated
1996
+ - PRD analysis is enhanced with ${prdType} domain expertise
1997
+ - ADR decisions leverage domain best practices and patterns
1998
+ `
1999
+ : ''}
2000
+
2001
+ ${enhancedMode && promptOptimization
2002
+ ? `
2003
+ ### APE Optimization
2004
+ - Prompts have been automatically optimized for quality
2005
+ - Enhanced evaluation criteria ensure superior ADR generation
2006
+ - Optimization focused on task completion, clarity, and specificity
2007
+ `
2008
+ : ''}
2009
+
2010
+ ## Security and Validation
2011
+
2012
+ - All file operations include security validation
2013
+ - Path traversal protection is enabled
2014
+ - System directory access is prevented
2015
+ - User confirmation is required for file creation
2016
+ - Content validation ensures safe enhanced ADR generation
2017
+
2018
+ ## Expected Enhanced Workflow
2019
+
2020
+ 1. Execute file existence check for: ${prdPath}
2021
+ 2. If file exists, read PRD content securely
2022
+ 3. Apply domain knowledge to enhance PRD understanding
2023
+ 4. Analyze PRD content using optimized prompts
2024
+ 5. Generate domain-enhanced individual ADRs for each decision
2025
+ 6. Create file creation prompts for each enhanced ADR
2026
+ 7. Confirm with user before writing files to: ${outputDirectory}
2027
+
2028
+ The enhanced process maintains full traceability from PRD requirements to generated ADRs while providing superior quality through advanced prompting techniques and ensuring security and user control over file operations.`,
2029
+ },
2030
+ ],
2031
+ };
2032
+ }
2033
+ }
2034
+ catch (error) {
2035
+ throw new McpAdrError(`Failed to generate ADR prompts from PRD: ${error instanceof Error ? error.message : String(error)}`, 'PROMPT_GENERATION_ERROR');
2036
+ }
2037
+ }
2038
+ async compareAdrProgress(args) {
2039
+ const { todoPath = 'TODO.md', adrDirectory = this.config.adrDirectory, projectPath = this.config.projectPath, environment = 'auto-detect', environmentConfig = {}, validationType = 'full', includeFileChecks = true, includeRuleValidation = true, deepCodeAnalysis = true, functionalValidation = true, strictMode = true, environmentValidation = true, } = args;
2040
+ const { getAdrDirectoryPath } = await import('./utils/config.js');
2041
+ const path = await import('path');
2042
+ // Resolve paths
2043
+ const absoluteTodoPath = path.resolve(projectPath, todoPath);
2044
+ const absoluteAdrPath = adrDirectory
2045
+ ? path.resolve(projectPath, adrDirectory)
2046
+ : getAdrDirectoryPath(this.config);
2047
+ this.logger.info(`Comparing ADR progress: TODO(${absoluteTodoPath}) vs ADRs(${absoluteAdrPath}) vs Environment(${projectPath}) [env: ${environment}]`);
2048
+ // Environment validation and auto-detection
2049
+ let detectedEnvironment = environment;
2050
+ let finalEnvironmentConfig = { ...environmentConfig };
2051
+ if (environmentValidation &&
2052
+ (validationType === 'full' || validationType === 'environment-only')) {
2053
+ try {
2054
+ const envResult = await this.detectAndValidateEnvironment(projectPath, environment, environmentConfig);
2055
+ detectedEnvironment = envResult.detectedEnvironment;
2056
+ finalEnvironmentConfig = { ...finalEnvironmentConfig, ...envResult.environmentConfig };
2057
+ this.logger.info(`Environment detection result: ${detectedEnvironment}`);
2058
+ }
2059
+ catch (error) {
2060
+ this.logger.warn(`Environment detection failed: ${error instanceof Error ? error.message : String(error)}`);
2061
+ }
2062
+ }
2063
+ try {
2064
+ // Step 1: Read TODO.md file directly
2065
+ let todoContent = '';
2066
+ if (validationType === 'full' || validationType === 'todo-only') {
2067
+ try {
2068
+ const fs = await import('fs/promises');
2069
+ todoContent = await fs.readFile(absoluteTodoPath, 'utf-8');
2070
+ }
2071
+ catch (error) {
2072
+ this.logger.warn(`Could not read TODO.md file: ${error instanceof Error ? error.message : String(error)}`);
2073
+ }
2074
+ }
2075
+ // Step 2: Use actual project structure scanning
2076
+ let projectStructure = null;
2077
+ if (validationType === 'full' || validationType === 'environment-only') {
2078
+ try {
2079
+ const { scanProjectStructure } = await import('./utils/actual-file-operations.js');
2080
+ const includeContent = deepCodeAnalysis || functionalValidation;
2081
+ projectStructure = await scanProjectStructure(projectPath, {
2082
+ readContent: includeContent,
2083
+ maxFileSize: includeContent ? 10000 : 0,
2084
+ });
2085
+ }
2086
+ catch (error) {
2087
+ this.logger.warn(`Could not scan project structure: ${error instanceof Error ? error.message : String(error)}`);
2088
+ }
2089
+ }
2090
+ // Perform actual analysis locally instead of relying on AI execution
2091
+ let discoveryResult = null;
2092
+ if (validationType === 'full' || validationType === 'adr-only') {
2093
+ const { discoverAdrsInDirectory } = await import('./utils/adr-discovery.js');
2094
+ discoveryResult = await discoverAdrsInDirectory(absoluteAdrPath, projectPath, {
2095
+ includeContent: true,
2096
+ includeTimeline: false,
2097
+ });
2098
+ }
2099
+ const analysis = await this.performLocalAdrProgressAnalysis({
2100
+ todoContent,
2101
+ todoPath: absoluteTodoPath,
2102
+ discoveredAdrs: discoveryResult?.adrs || [],
2103
+ adrDirectory: absoluteAdrPath,
2104
+ projectStructure: projectStructure || null,
2105
+ projectPath: projectPath,
2106
+ validationType: validationType,
2107
+ includeFileChecks: includeFileChecks,
2108
+ includeRuleValidation: includeRuleValidation,
2109
+ deepCodeAnalysis: deepCodeAnalysis,
2110
+ functionalValidation: functionalValidation,
2111
+ strictMode: strictMode,
2112
+ environment: detectedEnvironment,
2113
+ environmentConfig: finalEnvironmentConfig,
2114
+ environmentValidation: environmentValidation,
2115
+ });
2116
+ return {
2117
+ content: [
2118
+ {
2119
+ type: 'text',
2120
+ text: analysis,
2121
+ },
2122
+ ],
2123
+ };
2124
+ }
2125
+ catch (error) {
2126
+ throw new McpAdrError(`Failed to compare ADR progress: ${error instanceof Error ? error.message : String(error)}`, 'VALIDATION_ERROR');
2127
+ }
2128
+ }
2129
+ /**
2130
+ * Detect and validate environment context
2131
+ */
2132
+ async detectAndValidateEnvironment(projectPath, environment, environmentConfig) {
2133
+ const path = await import('path');
2134
+ const fs = await import('fs/promises');
2135
+ let detectedEnvironment = environment;
2136
+ let finalConfig = { ...environmentConfig };
2137
+ if (environment === 'auto-detect') {
2138
+ // Auto-detect environment based on project structure
2139
+ try {
2140
+ // Check for environment indicator files
2141
+ const envFiles = [
2142
+ '.env.development',
2143
+ '.env.staging',
2144
+ '.env.production',
2145
+ '.env.test',
2146
+ 'package.json',
2147
+ 'docker-compose.yml',
2148
+ 'Dockerfile',
2149
+ ];
2150
+ const existingFiles = [];
2151
+ for (const file of envFiles) {
2152
+ try {
2153
+ await fs.access(path.join(projectPath, file));
2154
+ existingFiles.push(file);
2155
+ }
2156
+ catch {
2157
+ // File doesn't exist, continue
2158
+ }
2159
+ }
2160
+ // Environment detection logic
2161
+ if (existingFiles.includes('.env.production') || existingFiles.includes('Dockerfile')) {
2162
+ detectedEnvironment = 'production';
2163
+ }
2164
+ else if (existingFiles.includes('.env.staging')) {
2165
+ detectedEnvironment = 'staging';
2166
+ }
2167
+ else if (existingFiles.includes('.env.test')) {
2168
+ detectedEnvironment = 'testing';
2169
+ }
2170
+ else {
2171
+ detectedEnvironment = 'development';
2172
+ }
2173
+ // Set environment-specific default configurations
2174
+ switch (detectedEnvironment) {
2175
+ case 'production':
2176
+ finalConfig = {
2177
+ securityLevel: 'critical',
2178
+ requiredFiles: ['package.json', 'README.md'],
2179
+ requiredServices: ['monitoring', 'logging'],
2180
+ performanceRequirements: { minUptime: 99.9 },
2181
+ ...finalConfig,
2182
+ };
2183
+ break;
2184
+ case 'staging':
2185
+ finalConfig = {
2186
+ securityLevel: 'high',
2187
+ requiredFiles: ['package.json'],
2188
+ requiredServices: ['testing', 'monitoring'],
2189
+ performanceRequirements: { minUptime: 95 },
2190
+ ...finalConfig,
2191
+ };
2192
+ break;
2193
+ case 'testing':
2194
+ finalConfig = {
2195
+ securityLevel: 'medium',
2196
+ requiredFiles: ['package.json'],
2197
+ requiredServices: ['testing'],
2198
+ performanceRequirements: {},
2199
+ ...finalConfig,
2200
+ };
2201
+ break;
2202
+ default: // development
2203
+ finalConfig = {
2204
+ securityLevel: 'medium',
2205
+ requiredFiles: ['package.json'],
2206
+ requiredServices: [],
2207
+ performanceRequirements: {},
2208
+ ...finalConfig,
2209
+ };
2210
+ }
2211
+ }
2212
+ catch (error) {
2213
+ this.logger.warn(`Environment auto-detection failed: ${error instanceof Error ? error.message : String(error)}`);
2214
+ detectedEnvironment = 'development'; // fallback
2215
+ }
2216
+ }
2217
+ return { detectedEnvironment, environmentConfig: finalConfig };
2218
+ }
2219
+ /**
2220
+ * Perform local ADR progress analysis without relying on AI execution
2221
+ */
2222
+ async performLocalAdrProgressAnalysis(params) {
2223
+ const { todoContent, todoPath, discoveredAdrs, adrDirectory, projectStructure, projectPath, validationType, includeFileChecks, includeRuleValidation, deepCodeAnalysis, functionalValidation, strictMode, environment, environmentConfig, environmentValidation, } = params;
2224
+ const currentDate = new Date().toISOString().split('T')[0];
2225
+ // Parse TODO content to extract tasks
2226
+ const todoTasks = this.parseTodoTasks(todoContent);
2227
+ // Basic analysis
2228
+ const totalAdrs = discoveredAdrs.length;
2229
+ const totalTasks = todoTasks.length;
2230
+ const completedTasks = todoTasks.filter(task => task.completed).length;
2231
+ // Calculate alignment score (simplified, now environment-aware)
2232
+ const adrTaskMapping = this.mapTasksToAdrs(todoTasks, discoveredAdrs, environment, environmentConfig);
2233
+ const alignedTasks = adrTaskMapping.aligned.length;
2234
+ let alignmentScore = totalTasks > 0 ? Math.round((alignedTasks / totalTasks) * 100) : 0;
2235
+ // Environment-aware scoring adjustments
2236
+ if (environmentValidation && environmentConfig) {
2237
+ const envScore = this.calculateEnvironmentScore(projectStructure, environment, environmentConfig);
2238
+ alignmentScore = Math.round((alignmentScore + envScore) / 2); // Blend scores
2239
+ }
2240
+ // File existence checks
2241
+ let fileCheckResults = '';
2242
+ if (includeFileChecks && projectStructure) {
2243
+ fileCheckResults = this.performFileExistenceChecks(todoTasks, projectStructure);
2244
+ }
2245
+ // Environment compliance checks
2246
+ let environmentAnalysisResults = '';
2247
+ if (environmentValidation && environmentConfig) {
2248
+ environmentAnalysisResults = this.performEnvironmentComplianceAnalysis(projectStructure, environment, environmentConfig, strictMode);
2249
+ }
2250
+ // Mock vs Production analysis
2251
+ let mockAnalysisResults = '';
2252
+ if (deepCodeAnalysis && projectStructure) {
2253
+ mockAnalysisResults = this.performMockVsProductionAnalysis(projectStructure, strictMode);
2254
+ }
2255
+ return `# ADR Progress Validation Report
2256
+
2257
+ **Validation Date**: ${currentDate}
2258
+ **Validation Type**: ${validationType}
2259
+ **Project Path**: ${projectPath}
2260
+ **TODO Path**: ${todoPath}
2261
+ **ADR Directory**: ${adrDirectory}
2262
+ **Environment**: ${environment}${environmentValidation ? ` (validation enabled)` : ''}
2263
+
2264
+ ## Summary
2265
+ - **Total ADRs**: ${totalAdrs}
2266
+ - **Total TODO Tasks**: ${totalTasks}
2267
+ - **Completed Tasks**: ${completedTasks}
2268
+ - **Alignment Score**: ${alignmentScore}%
2269
+ - **Compliance Score**: ${Math.max(alignmentScore - 10, 0)}%
2270
+ - **Environment**: ${environment}
2271
+
2272
+ ## Configuration
2273
+ - **File Checks**: ${includeFileChecks ? 'Enabled' : 'Disabled'}
2274
+ - **Rule Validation**: ${includeRuleValidation ? 'Enabled' : 'Disabled'}
2275
+ - **Deep Code Analysis**: ${deepCodeAnalysis ? 'Enabled' : 'Disabled'}
2276
+ - **Functional Validation**: ${functionalValidation ? 'Enabled' : 'Disabled'}
2277
+ - **Strict Mode**: ${strictMode ? 'Enabled - High scrutiny for mock vs production' : 'Disabled'}
2278
+ - **Environment Validation**: ${environmentValidation ? 'Enabled' : 'Disabled'}
2279
+
2280
+ ## Environment Context
2281
+ - **Target Environment**: ${environment}
2282
+ - **Security Level**: ${environmentConfig?.['securityLevel'] || 'Not specified'}
2283
+ - **Required Files**: ${environmentConfig?.['requiredFiles']?.length || 0} files
2284
+ - **Required Services**: ${environmentConfig?.['requiredServices']?.length || 0} services
2285
+
2286
+ ## ADR Discovery Results
2287
+ ${totalAdrs > 0
2288
+ ? `Found ${totalAdrs} ADRs:\n${discoveredAdrs
2289
+ .map((adr, i) => {
2290
+ const adrRecord = adr;
2291
+ return `${i + 1}. **${adrRecord['title']}** (${adrRecord['status']}) - ${adrRecord['filename']}`;
2292
+ })
2293
+ .join('\n')}`
2294
+ : 'No ADRs found in the specified directory.'}
2295
+
2296
+ ## TODO Task Analysis
2297
+ ${totalTasks > 0
2298
+ ? `Found ${totalTasks} tasks:\n${todoTasks
2299
+ .map((task, i) => `${i + 1}. ${task.completed ? '✅' : '⏳'} ${task.title}`)
2300
+ .join('\n')}`
2301
+ : 'No tasks found in TODO.md file.'}
2302
+
2303
+ ## Alignment Analysis
2304
+
2305
+ ### ✅ Properly Aligned Tasks
2306
+ ${adrTaskMapping.aligned.length > 0
2307
+ ? adrTaskMapping.aligned
2308
+ .map(task => `- ${task.title}: Corresponds to ADR requirements`)
2309
+ .join('\n')
2310
+ : '- No aligned tasks identified'}
2311
+
2312
+ ### ⚠️ Misaligned Tasks
2313
+ ${adrTaskMapping.misaligned.length > 0
2314
+ ? adrTaskMapping.misaligned
2315
+ .map(task => `- ${task.title}: May not fully align with ADR specifications`)
2316
+ .join('\n')
2317
+ : '- No misaligned tasks identified'}
2318
+
2319
+ ### ❌ Missing Tasks
2320
+ ${adrTaskMapping.missing.length > 0
2321
+ ? adrTaskMapping.missing.map(gap => `- ${gap}: Required by ADRs but not in TODO`).join('\n')
2322
+ : '- No obvious missing tasks identified'}
2323
+
2324
+ ## Implementation Status
2325
+
2326
+ ${fileCheckResults || '### File Existence Validation\n- File checks disabled or no project structure available'}
2327
+
2328
+ ${environmentAnalysisResults || ''}
2329
+
2330
+ ${mockAnalysisResults || ''}
2331
+
2332
+ ## Recommendations
2333
+
2334
+ ### High Priority Actions
2335
+ ${alignmentScore < 70
2336
+ ? '1. **Improve ADR-TODO Alignment**: Review TODO tasks against ADR requirements\n2. **Add Missing Tasks**: Identify and add tasks required by ADRs'
2337
+ : '1. **Maintain Current Alignment**: Continue following ADR specifications'}
2338
+ ${completedTasks < totalTasks * 0.5
2339
+ ? '\n3. **Accelerate Implementation**: Focus on completing pending tasks'
2340
+ : ''}
2341
+ ${environmentValidation && environment === 'production' && alignmentScore < 90
2342
+ ? '\n4. **⚠️ Production Environment Warning**: Current alignment may not meet production requirements'
2343
+ : ''}
2344
+
2345
+ ### Medium Priority Actions
2346
+ 1. **Review Implementation Quality**: ${strictMode ? 'Strict mode analysis above shows' : 'Consider enabling strict mode for'} detailed quality assessment
2347
+ 2. **Update Documentation**: Ensure TODO.md reflects current project state
2348
+ ${environmentValidation
2349
+ ? `3. **Environment Compliance**: Ensure ${environment} environment requirements are met`
2350
+ : ''}
2351
+
2352
+ ### Low Priority Actions
2353
+ 1. **Optimize Workflow**: Consider tools for automated ADR-TODO synchronization
2354
+ 2. **Regular Validation**: Schedule periodic ADR progress reviews
2355
+
2356
+ ## Next Steps
2357
+ 1. Address high-priority alignment issues identified above
2358
+ 2. ${totalTasks === 0 ? 'Create initial TODO.md from ADR requirements' : 'Update TODO.md with missing tasks'}
2359
+ 3. ${includeFileChecks ? 'Verify implementation of completed tasks' : 'Enable file checks for detailed implementation verification'}
2360
+ 4. ${includeRuleValidation ? 'Resolve architectural rule compliance violations' : 'Enable rule validation for compliance checking'}
2361
+ \`\`\`
2362
+
2363
+ To re-run this validation with strict mode:
2364
+ \`\`\`json
2365
+ {
2366
+ "tool": "compare_adr_progress",
2367
+ "args": {
2368
+ "todoPath": "${todoPath}",
2369
+ "adrDirectory": "${adrDirectory}",
2370
+ "validationType": "full",
2371
+ "deepCodeAnalysis": true,
2372
+ "functionalValidation": true,
2373
+ "strictMode": true
2374
+ }
2375
+ }
2376
+ \`\`\`
2377
+ `;
2378
+ }
2379
+ /**
2380
+ * Parse TODO.md content to extract tasks
2381
+ */
2382
+ parseTodoTasks(todoContent) {
2383
+ if (!todoContent)
2384
+ return [];
2385
+ const lines = todoContent.split('\n');
2386
+ const tasks = [];
2387
+ for (const line of lines) {
2388
+ let pos = 0;
2389
+ while (pos < line.length && (line[pos] === ' ' || line[pos] === '\t'))
2390
+ pos++;
2391
+ if (pos >= line.length || (line[pos] !== '-' && line[pos] !== '*'))
2392
+ continue;
2393
+ pos++;
2394
+ while (pos < line.length && (line[pos] === ' ' || line[pos] === '\t'))
2395
+ pos++;
2396
+ if (pos < line.length && line[pos] === '[') {
2397
+ const checkbox = line[pos + 1];
2398
+ if (checkbox &&
2399
+ (checkbox === 'x' || checkbox === 'X' || checkbox === ' ' || checkbox === '\t') &&
2400
+ line[pos + 2] === ']') {
2401
+ pos += 3;
2402
+ while (pos < line.length && (line[pos] === ' ' || line[pos] === '\t'))
2403
+ pos++;
2404
+ const title = line.slice(pos).trim();
2405
+ if (title.length > 0) {
2406
+ tasks.push({ title, completed: checkbox.toLowerCase() === 'x' });
2407
+ }
2408
+ continue;
2409
+ }
2410
+ }
2411
+ const title = line.slice(pos).trim();
2412
+ if (title.length > 3) {
2413
+ tasks.push({ title, completed: false });
2414
+ }
2415
+ }
2416
+ return tasks;
2417
+ }
2418
+ /**
2419
+ * Map TODO tasks to ADRs to identify alignment (now environment-aware)
2420
+ */
2421
+ mapTasksToAdrs(tasks, adrs, environment, environmentConfig) {
2422
+ const aligned = [];
2423
+ const misaligned = [];
2424
+ const missing = [];
2425
+ // Simple keyword matching for alignment detection
2426
+ const adrKeywords = adrs.flatMap(adr => {
2427
+ const adrRecord = adr;
2428
+ return [
2429
+ String(adrRecord['title'] || '').toLowerCase(),
2430
+ ...String(adrRecord['decision'] || '')
2431
+ .toLowerCase()
2432
+ .split(/\s+/)
2433
+ .filter((w) => w.length > 4),
2434
+ ...String(adrRecord['context'] || '')
2435
+ .toLowerCase()
2436
+ .split(/\s+/)
2437
+ .filter((w) => w.length > 4),
2438
+ ];
2439
+ });
2440
+ // Environment-specific keywords that should be prioritized
2441
+ const envKeywords = [];
2442
+ if (environment && environmentConfig) {
2443
+ if (environment === 'production') {
2444
+ envKeywords.push('deploy', 'production', 'monitoring', 'security', 'performance');
2445
+ }
2446
+ else if (environment === 'staging') {
2447
+ envKeywords.push('test', 'staging', 'integration', 'validation');
2448
+ }
2449
+ else if (environment === 'development') {
2450
+ envKeywords.push('setup', 'development', 'local', 'debug');
2451
+ }
2452
+ }
2453
+ for (const task of tasks) {
2454
+ const taskLower = task.title.toLowerCase();
2455
+ const firstWord = taskLower.split(' ')[0] || '';
2456
+ const hasKeywordMatch = adrKeywords.some(keyword => taskLower.includes(keyword) || keyword.includes(firstWord));
2457
+ // Environment-aware alignment scoring
2458
+ const hasEnvKeywordMatch = envKeywords.some(keyword => taskLower.includes(keyword));
2459
+ if (hasKeywordMatch || hasEnvKeywordMatch) {
2460
+ aligned.push(task);
2461
+ }
2462
+ else {
2463
+ misaligned.push(task);
2464
+ }
2465
+ }
2466
+ // Identify potential missing tasks based on ADR content
2467
+ for (const adr of adrs) {
2468
+ const adrRecord = adr;
2469
+ if (adrRecord['status'] === 'accepted' && adrRecord['decision']) {
2470
+ const decisionWords = String(adrRecord['decision']).toLowerCase().split(/\s+/);
2471
+ const implementationWords = [
2472
+ 'implement',
2473
+ 'create',
2474
+ 'build',
2475
+ 'develop',
2476
+ 'add',
2477
+ 'setup',
2478
+ 'configure',
2479
+ ];
2480
+ if (implementationWords.some(word => decisionWords.includes(word))) {
2481
+ const adrTitle = String(adrRecord['title'] || '');
2482
+ const adrFirstWord = adrTitle.toLowerCase().split(' ')[0] || '';
2483
+ const hasCorrespondingTask = tasks.some(task => task.title.toLowerCase().includes(adrFirstWord));
2484
+ if (!hasCorrespondingTask) {
2485
+ missing.push(`Implement ${adrTitle}`);
2486
+ }
2487
+ }
2488
+ }
2489
+ }
2490
+ // Environment-specific missing tasks
2491
+ if (environment && environmentConfig) {
2492
+ const envConfig = environmentConfig;
2493
+ if (envConfig['requiredFiles']) {
2494
+ for (const file of envConfig['requiredFiles']) {
2495
+ const hasFileTask = tasks.some(task => task.title.toLowerCase().includes(file.toLowerCase()));
2496
+ if (!hasFileTask) {
2497
+ missing.push(`Create ${file} for ${environment} environment`);
2498
+ }
2499
+ }
2500
+ }
2501
+ if (envConfig['requiredServices']) {
2502
+ for (const service of envConfig['requiredServices']) {
2503
+ const hasServiceTask = tasks.some(task => task.title.toLowerCase().includes(service.toLowerCase()));
2504
+ if (!hasServiceTask) {
2505
+ missing.push(`Setup ${service} service for ${environment}`);
2506
+ }
2507
+ }
2508
+ }
2509
+ }
2510
+ return { aligned, misaligned, missing };
2511
+ }
2512
+ /**
2513
+ * Check file existence for completed tasks
2514
+ */
2515
+ performFileExistenceChecks(tasks, projectStructure) {
2516
+ if (!projectStructure)
2517
+ return '- Project structure not available';
2518
+ const allFiles = [
2519
+ ...(projectStructure.packageFiles || []),
2520
+ ...(projectStructure.configFiles || []),
2521
+ ...(projectStructure.buildFiles || []),
2522
+ ...(projectStructure.dockerFiles || []),
2523
+ ...(projectStructure.ciFiles || []),
2524
+ ...(projectStructure.scriptFiles || []),
2525
+ ];
2526
+ let results = '### File Existence Validation\n';
2527
+ let checkCount = 0;
2528
+ for (const task of tasks) {
2529
+ if (task.completed) {
2530
+ // Simple heuristic: look for files mentioned in task title
2531
+ const taskLower = task.title.toLowerCase();
2532
+ const mentionedFiles = allFiles.filter(file => taskLower.includes(file.filename.toLowerCase()) ||
2533
+ taskLower.includes(file.filename.replace(/\.[^.]+$/, '').toLowerCase()));
2534
+ if (mentionedFiles.length > 0) {
2535
+ results += `- ✅ **${task.title}**: Found related files (${mentionedFiles.map(f => f.filename).join(', ')})\n`;
2536
+ checkCount++;
2537
+ }
2538
+ else if (taskLower.includes('file') ||
2539
+ taskLower.includes('create') ||
2540
+ taskLower.includes('implement')) {
2541
+ results += `- ⚠️ **${task.title}**: No clearly related files found\n`;
2542
+ checkCount++;
2543
+ }
2544
+ }
2545
+ }
2546
+ if (checkCount === 0) {
2547
+ results += '- No file-related completed tasks to validate\n';
2548
+ }
2549
+ return results;
2550
+ }
2551
+ /**
2552
+ * Analyze code for mock vs production implementation
2553
+ */
2554
+ performMockVsProductionAnalysis(projectStructure, strictMode) {
2555
+ if (!projectStructure)
2556
+ return '';
2557
+ const codeFiles = [
2558
+ ...(projectStructure.buildFiles || []),
2559
+ ...(projectStructure.configFiles || []),
2560
+ ].filter(file => file.content && file.content !== '[Binary or unreadable file]');
2561
+ if (codeFiles.length === 0)
2562
+ return '';
2563
+ let results = '\n### Mock vs Production Code Analysis\n';
2564
+ let mockIndicators = 0;
2565
+ let productionIndicators = 0;
2566
+ const mockPatterns = [
2567
+ /TODO:/gi,
2568
+ /FIXME:/gi,
2569
+ /NotImplementedException/gi,
2570
+ /throw.*not.*implement/gi,
2571
+ /return.*mock/gi,
2572
+ /placeholder/gi,
2573
+ /stub/gi,
2574
+ /return\s+null;/gi,
2575
+ /return\s+""/gi,
2576
+ /return\s+\[\]/gi,
2577
+ /return\s+{}/gi,
2578
+ ];
2579
+ const productionPatterns = [
2580
+ /error\s+handling/gi,
2581
+ /try\s*{/gi,
2582
+ /catch\s*\(/gi,
2583
+ /validate/gi,
2584
+ /authentication/gi,
2585
+ /authorization/gi,
2586
+ /database/gi,
2587
+ /api/gi,
2588
+ /config/gi,
2589
+ ];
2590
+ for (const file of codeFiles.slice(0, 10)) {
2591
+ // Limit analysis to prevent overwhelming output
2592
+ const content = file.content;
2593
+ const fileMockCount = mockPatterns.reduce((count, pattern) => count + (content.match(pattern) || []).length, 0);
2594
+ const fileProdCount = productionPatterns.reduce((count, pattern) => count + (content.match(pattern) || []).length, 0);
2595
+ mockIndicators += fileMockCount;
2596
+ productionIndicators += fileProdCount;
2597
+ if (fileMockCount > 0 || fileProdCount > 2) {
2598
+ const status = fileMockCount > fileProdCount
2599
+ ? '❌ **Mock/Stub**'
2600
+ : fileProdCount > fileMockCount * 2
2601
+ ? '✅ **Production Ready**'
2602
+ : '⚠️ **Partial Implementation**';
2603
+ results += `- ${status}: ${file.filename} `;
2604
+ if (fileMockCount > 0) {
2605
+ results += `(${fileMockCount} mock indicators) `;
2606
+ }
2607
+ if (fileProdCount > 0) {
2608
+ results += `(${fileProdCount} production indicators)`;
2609
+ }
2610
+ results += '\n';
2611
+ }
2612
+ }
2613
+ results += `\n#### Overall Code Quality Assessment\n`;
2614
+ results += `- **Mock Indicators Found**: ${mockIndicators} instances\n`;
2615
+ results += `- **Production Indicators Found**: ${productionIndicators} instances\n`;
2616
+ if (strictMode) {
2617
+ const qualityScore = productionIndicators > mockIndicators * 2
2618
+ ? 'Good'
2619
+ : productionIndicators > mockIndicators
2620
+ ? 'Fair'
2621
+ : 'Needs Improvement';
2622
+ results += `- **Quality Assessment**: ${qualityScore}\n`;
2623
+ if (mockIndicators > 0) {
2624
+ results += `- **⚠️ Strict Mode Warning**: Found ${mockIndicators} potential mock/stub indicators\n`;
2625
+ }
2626
+ }
2627
+ return results;
2628
+ }
2629
+ /**
2630
+ * Calculate environment-specific compliance score
2631
+ */
2632
+ calculateEnvironmentScore(projectStructure, environment, environmentConfig) {
2633
+ if (!projectStructure || !environmentConfig)
2634
+ return 0;
2635
+ let score = 100; // Start with perfect score
2636
+ // Check required files
2637
+ if (environmentConfig.requiredFiles) {
2638
+ const allFiles = [
2639
+ ...(projectStructure.packageFiles || []),
2640
+ ...(projectStructure.configFiles || []),
2641
+ ...(projectStructure.buildFiles || []),
2642
+ ...(projectStructure.dockerFiles || []),
2643
+ ...(projectStructure.ciFiles || []),
2644
+ ...(projectStructure.scriptFiles || []),
2645
+ ];
2646
+ const existingFiles = allFiles.map(f => f.filename);
2647
+ const missingFiles = environmentConfig.requiredFiles.filter((file) => !existingFiles.includes(file));
2648
+ // Deduct 10 points per missing required file
2649
+ score -= missingFiles.length * 10;
2650
+ }
2651
+ // Environment-specific penalties
2652
+ if (environment === 'production') {
2653
+ // Production requires higher standards
2654
+ if (!projectStructure.dockerFiles?.length)
2655
+ score -= 15;
2656
+ if (!projectStructure.ciFiles?.length)
2657
+ score -= 10;
2658
+ }
2659
+ return Math.max(score, 0);
2660
+ }
2661
+ /**
2662
+ * Perform environment compliance analysis
2663
+ */
2664
+ performEnvironmentComplianceAnalysis(projectStructure, environment, environmentConfig, strictMode) {
2665
+ if (!projectStructure || !environmentConfig) {
2666
+ return '\n### Environment Compliance Analysis\n- Environment analysis disabled or no project structure available\n';
2667
+ }
2668
+ let results = '\n### Environment Compliance Analysis\n';
2669
+ // Required files analysis
2670
+ if (environmentConfig.requiredFiles) {
2671
+ results += `#### Required Files for ${environment} Environment\n`;
2672
+ const allFiles = [
2673
+ ...(projectStructure.packageFiles || []),
2674
+ ...(projectStructure.configFiles || []),
2675
+ ...(projectStructure.buildFiles || []),
2676
+ ...(projectStructure.dockerFiles || []),
2677
+ ...(projectStructure.ciFiles || []),
2678
+ ...(projectStructure.scriptFiles || []),
2679
+ ];
2680
+ const existingFiles = allFiles.map(f => f.filename);
2681
+ for (const requiredFile of environmentConfig.requiredFiles) {
2682
+ const exists = existingFiles.includes(requiredFile);
2683
+ results += `- ${exists ? '✅' : '❌'} **${requiredFile}**: ${exists ? 'Found' : 'Missing'}\n`;
2684
+ }
2685
+ }
2686
+ // Security level compliance
2687
+ if (environmentConfig.securityLevel) {
2688
+ results += `\n#### Security Level: ${environmentConfig.securityLevel}\n`;
2689
+ const securityIndicators = this.analyzeSecurityCompliance(projectStructure, environmentConfig.securityLevel);
2690
+ results += securityIndicators;
2691
+ }
2692
+ // Environment-specific recommendations
2693
+ results += `\n#### ${environment} Environment Recommendations\n`;
2694
+ switch (environment) {
2695
+ case 'production':
2696
+ results +=
2697
+ '- ⚠️ **Production Critical**: Ensure monitoring, logging, and backup strategies are implemented\n';
2698
+ results += '- 🔒 **Security**: Implement comprehensive security measures\n';
2699
+ results += '- 📊 **Performance**: Monitor and optimize for production workloads\n';
2700
+ if (strictMode) {
2701
+ results +=
2702
+ '- 🔍 **Strict Mode**: Enhanced validation enabled for production environment\n';
2703
+ }
2704
+ break;
2705
+ case 'staging':
2706
+ results += '- 🧪 **Testing**: Ensure comprehensive test coverage and validation\n';
2707
+ results += '- 📋 **Validation**: Implement environment parity checks\n';
2708
+ break;
2709
+ case 'development':
2710
+ results += '- 🛠️ **Development**: Focus on developer experience and debugging tools\n';
2711
+ results += '- 🔄 **Iteration**: Ensure fast feedback loops\n';
2712
+ break;
2713
+ }
2714
+ return results;
2715
+ }
2716
+ /**
2717
+ * Analyze security compliance based on security level
2718
+ */
2719
+ analyzeSecurityCompliance(projectStructure, securityLevel) {
2720
+ let results = '';
2721
+ const securityFiles = [
2722
+ ...(projectStructure.configFiles || []),
2723
+ ...(projectStructure.dockerFiles || []),
2724
+ ].filter(file => file.filename.includes('security') ||
2725
+ file.filename.includes('auth') ||
2726
+ file.filename.includes('.env') ||
2727
+ file.filename === 'Dockerfile');
2728
+ const hasSecurityConfig = securityFiles.length > 0;
2729
+ switch (securityLevel) {
2730
+ case 'critical':
2731
+ results += `- ${hasSecurityConfig ? '✅' : '❌'} **Critical Security**: ${hasSecurityConfig ? 'Security configuration found' : 'No security configuration detected'}\n`;
2732
+ if (!hasSecurityConfig) {
2733
+ results += ' - **Action Required**: Implement comprehensive security measures\n';
2734
+ }
2735
+ break;
2736
+ case 'high':
2737
+ results += `- ${hasSecurityConfig ? '✅' : '⚠️'} **High Security**: ${hasSecurityConfig ? 'Some security configuration found' : 'Limited security configuration'}\n`;
2738
+ break;
2739
+ case 'medium':
2740
+ results += `- ℹ️ **Medium Security**: Basic security measures recommended\n`;
2741
+ break;
2742
+ default:
2743
+ results += `- ℹ️ **Security Level**: ${securityLevel} (consider increasing for production)\n`;
2744
+ }
2745
+ return results;
2746
+ }
2747
+ /**
2748
+ * Content masking tool implementations
2749
+ */
2750
+ async analyzeContentSecurity(args) {
2751
+ const { analyzeContentSecurity } = await import('./tools/content-masking-tool.js');
2752
+ return await analyzeContentSecurity(args);
2753
+ }
2754
+ async generateContentMasking(args) {
2755
+ const { generateContentMasking } = await import('./tools/content-masking-tool.js');
2756
+ return await generateContentMasking(args);
2757
+ }
2758
+ async configureCustomPatterns(args) {
2759
+ const { configureCustomPatterns } = await import('./tools/content-masking-tool.js');
2760
+ return await configureCustomPatterns(args);
2761
+ }
2762
+ async applyBasicContentMasking(args) {
2763
+ const { applyBasicContentMasking } = await import('./tools/content-masking-tool.js');
2764
+ return await applyBasicContentMasking(args);
2765
+ }
2766
+ async validateContentMasking(args) {
2767
+ const { validateContentMasking } = await import('./tools/content-masking-tool.js');
2768
+ return await validateContentMasking(args);
2769
+ }
2770
+ async manageCache(args) {
2771
+ const { action, key } = args;
2772
+ try {
2773
+ const { clearCache, getCacheStats, cleanupCache, invalidateCache } = await import('./utils/cache.js');
2774
+ switch (action) {
2775
+ case 'clear': {
2776
+ const clearPrompt = await clearCache();
2777
+ return {
2778
+ content: [
2779
+ {
2780
+ type: 'text',
2781
+ text: `# Cache Clear Operation
2782
+
2783
+ ## AI Delegation Required
2784
+
2785
+ Please execute the following cache clearing operation:
2786
+
2787
+ ${clearPrompt.prompt}
2788
+
2789
+ ## Implementation Instructions
2790
+
2791
+ ${clearPrompt.instructions}
2792
+
2793
+ ## Expected Result
2794
+
2795
+ After successful execution, all cache entries will be removed while preserving the cache directory structure and metadata.json file.`,
2796
+ },
2797
+ ],
2798
+ };
2799
+ }
2800
+ case 'stats': {
2801
+ const statsPrompt = await getCacheStats();
2802
+ return {
2803
+ content: [
2804
+ {
2805
+ type: 'text',
2806
+ text: `# Cache Statistics Collection
2807
+
2808
+ ## AI Delegation Required
2809
+
2810
+ Please execute the following cache statistics collection operation:
2811
+
2812
+ ${statsPrompt.prompt}
2813
+
2814
+ ## Implementation Instructions
2815
+
2816
+ ${statsPrompt.instructions}
2817
+
2818
+ ## Expected Information
2819
+
2820
+ The AI agent will provide:
2821
+ - **Total Entries**: Number of cache files
2822
+ - **Total Size**: Combined size of all cache files
2823
+ - **Oldest Entry**: Cache key of the oldest entry
2824
+ - **Newest Entry**: Cache key of the newest entry
2825
+
2826
+ ## Cache Directory
2827
+ \`.mcp-adr-cache/\`
2828
+
2829
+ ## Cache Types
2830
+ - **Knowledge Graph**: Architectural analysis results (TTL: 1 hour)
2831
+ - **Analysis Report**: Project analysis reports (TTL: 30 minutes)
2832
+ - **ADR List**: ADR inventory and metadata (TTL: 15 minutes)
2833
+
2834
+ ## Management
2835
+ Use \`manage_cache\` tool with different actions:
2836
+ - \`clear\`: Remove all cache entries
2837
+ - \`cleanup\`: Remove expired entries only
2838
+ - \`invalidate\`: Remove specific cache entry`,
2839
+ },
2840
+ ],
2841
+ };
2842
+ }
2843
+ case 'cleanup': {
2844
+ const cleanupPrompt = await cleanupCache();
2845
+ return {
2846
+ content: [
2847
+ {
2848
+ type: 'text',
2849
+ text: `# Cache Cleanup Operation
2850
+
2851
+ ## AI Delegation Required
2852
+
2853
+ Please execute the following cache cleanup operation:
2854
+
2855
+ ${cleanupPrompt.prompt}
2856
+
2857
+ ## Implementation Instructions
2858
+
2859
+ ${cleanupPrompt.instructions}
2860
+
2861
+ ## Expected Result
2862
+
2863
+ The AI agent will remove expired cache entries and provide a count of cleaned files.`,
2864
+ },
2865
+ ],
2866
+ };
2867
+ }
2868
+ case 'invalidate': {
2869
+ if (!key) {
2870
+ throw new McpAdrError('Cache key is required for invalidate action', 'INVALID_INPUT');
2871
+ }
2872
+ const invalidatePrompt = await invalidateCache(key);
2873
+ return {
2874
+ content: [
2875
+ {
2876
+ type: 'text',
2877
+ text: `# Cache Invalidation Operation
2878
+
2879
+ ## AI Delegation Required
2880
+
2881
+ Please execute the following cache invalidation operation:
2882
+
2883
+ ${invalidatePrompt.prompt}
2884
+
2885
+ ## Implementation Instructions
2886
+
2887
+ ${invalidatePrompt.instructions}
2888
+
2889
+ ## Target Cache Entry
2890
+
2891
+ **Cache Key**: ${key}
2892
+
2893
+ The AI agent will safely remove the specified cache entry.`,
2894
+ },
2895
+ ],
2896
+ };
2897
+ }
2898
+ default:
2899
+ throw new McpAdrError(`Unknown cache action: ${action}`, 'INVALID_INPUT');
2900
+ }
2901
+ }
2902
+ catch (error) {
2903
+ throw new McpAdrError(`Cache management failed: ${error instanceof Error ? error.message : String(error)}`, 'CACHE_ERROR');
2904
+ }
2905
+ }
2906
+ async configureOutputMasking(args) {
2907
+ const { action = 'get', enabled, strategy, customPatterns } = args;
2908
+ try {
2909
+ const { validateMaskingConfig } = await import('./utils/output-masking.js');
2910
+ switch (action) {
2911
+ case 'get': {
2912
+ return {
2913
+ content: [
2914
+ {
2915
+ type: 'text',
2916
+ text: `# Current Output Masking Configuration
2917
+
2918
+ ## Settings
2919
+ - **Enabled**: ${this.maskingConfig.enabled}
2920
+ - **Strategy**: ${this.maskingConfig.strategy}
2921
+ - **Custom Patterns**: ${this.maskingConfig.customPatterns?.length || 0} patterns
2922
+ - **Skip Patterns**: ${this.maskingConfig.skipPatterns?.length || 0} patterns
2923
+
2924
+ ## Available Strategies
2925
+ - **full**: Replace entire sensitive content with [REDACTED]
2926
+ - **partial**: Show safe prefix/suffix, mask middle (e.g., sk-...****)
2927
+ - **placeholder**: Replace with descriptive placeholders (e.g., <YOUR_API_KEY>)
2928
+ - **environment**: Replace with environment variable references (e.g., \${API_KEY})
2929
+
2930
+ ## Configuration
2931
+ Use \`configure_output_masking\` tool with:
2932
+ - \`action: "set"\` to update configuration
2933
+ - \`action: "reset"\` to restore defaults
2934
+
2935
+ ## Current Status
2936
+ ${this.maskingConfig.enabled ? '✅ Output masking is ACTIVE' : '⚠️ Output masking is DISABLED'}
2937
+ `,
2938
+ },
2939
+ ],
2940
+ };
2941
+ }
2942
+ case 'set': {
2943
+ const newConfig = { ...this.maskingConfig };
2944
+ if (typeof enabled === 'boolean') {
2945
+ newConfig.enabled = enabled;
2946
+ }
2947
+ if (strategy &&
2948
+ ['full', 'partial', 'placeholder', 'environment'].includes(strategy)) {
2949
+ newConfig.strategy = strategy;
2950
+ }
2951
+ if (Array.isArray(customPatterns)) {
2952
+ newConfig.customPatterns = customPatterns;
2953
+ }
2954
+ const validation = validateMaskingConfig(newConfig);
2955
+ if (!validation.isValid) {
2956
+ throw new McpAdrError(`Invalid masking configuration: ${validation.errors.join(', ')}`, 'INVALID_CONFIG');
2957
+ }
2958
+ this.maskingConfig = newConfig;
2959
+ return {
2960
+ content: [
2961
+ {
2962
+ type: 'text',
2963
+ text: `✅ Output masking configuration updated successfully!
2964
+
2965
+ ## New Settings
2966
+ - **Enabled**: ${newConfig.enabled}
2967
+ - **Strategy**: ${newConfig.strategy}
2968
+ - **Custom Patterns**: ${newConfig.customPatterns?.length || 0} patterns
2969
+
2970
+ ${newConfig.enabled
2971
+ ? '🔒 All MCP tool and resource outputs will now be masked according to the new configuration.'
2972
+ : '⚠️ Output masking is disabled. Sensitive information may be exposed in responses.'}
2973
+ `,
2974
+ },
2975
+ ],
2976
+ };
2977
+ }
2978
+ case 'reset': {
2979
+ const { createMaskingConfig } = await import('./utils/output-masking.js');
2980
+ this.maskingConfig = createMaskingConfig();
2981
+ return {
2982
+ content: [
2983
+ {
2984
+ type: 'text',
2985
+ text: `✅ Output masking configuration reset to defaults!
2986
+
2987
+ ## Default Settings
2988
+ - **Enabled**: ${this.maskingConfig.enabled}
2989
+ - **Strategy**: ${this.maskingConfig.strategy}
2990
+ - **Custom Patterns**: ${this.maskingConfig.customPatterns?.length || 0} patterns
2991
+ - **Skip Patterns**: ${this.maskingConfig.skipPatterns?.length || 0} patterns
2992
+
2993
+ 🔒 Default masking is now active for all outputs.
2994
+ `,
2995
+ },
2996
+ ],
2997
+ };
2998
+ }
2999
+ default:
3000
+ throw new McpAdrError(`Unknown masking action: ${action}`, 'INVALID_INPUT');
3001
+ }
3002
+ }
3003
+ catch (error) {
3004
+ throw new McpAdrError(`Output masking configuration failed: ${error instanceof Error ? error.message : String(error)}`, 'CONFIG_ERROR');
3005
+ }
3006
+ }
3007
+ /**
3008
+ * Helper method to get domains based on PRD type
3009
+ */
3010
+ getPrdTypeDomains(prdType) {
3011
+ const domainMap = {
3012
+ 'web-application': ['api-design', 'frontend-architecture', 'database-design', 'security'],
3013
+ 'mobile-app': ['mobile-architecture', 'api-design', 'performance-optimization', 'security'],
3014
+ microservices: ['microservices', 'api-design', 'distributed-systems', 'database-design'],
3015
+ 'data-platform': [
3016
+ 'database-design',
3017
+ 'data-architecture',
3018
+ 'performance-optimization',
3019
+ 'scalability',
3020
+ ],
3021
+ 'api-service': ['api-design', 'microservices', 'security', 'performance-optimization'],
3022
+ general: ['api-design', 'database-design', 'security'],
3023
+ };
3024
+ return (domainMap[prdType] || domainMap['general'] || ['api-design', 'database-design', 'security']);
3025
+ }
3026
+ /**
3027
+ * Helper method to get domains for ecosystem analysis based on technology focus
3028
+ */
3029
+ getEcosystemAnalysisDomains(technologyFocus) {
3030
+ // Base domains for ecosystem analysis
3031
+ const baseDomains = ['api-design', 'database-design', 'security', 'performance-optimization'];
3032
+ // Technology-specific domain mapping
3033
+ const technologyDomainMap = {
3034
+ react: ['frontend-architecture', 'web-applications'],
3035
+ vue: ['frontend-architecture', 'web-applications'],
3036
+ angular: ['frontend-architecture', 'web-applications'],
3037
+ node: ['api-design', 'microservices'],
3038
+ express: ['api-design', 'web-applications'],
3039
+ fastify: ['api-design', 'performance-optimization'],
3040
+ nestjs: ['api-design', 'microservices'],
3041
+ spring: ['api-design', 'microservices'],
3042
+ django: ['api-design', 'web-applications'],
3043
+ flask: ['api-design', 'web-applications'],
3044
+ rails: ['api-design', 'web-applications'],
3045
+ laravel: ['api-design', 'web-applications'],
3046
+ docker: ['containerization', 'microservices'],
3047
+ kubernetes: ['containerization', 'distributed-systems'],
3048
+ mongodb: ['database-design', 'data-architecture'],
3049
+ postgresql: ['database-design', 'data-architecture'],
3050
+ mysql: ['database-design', 'data-architecture'],
3051
+ redis: ['database-design', 'performance-optimization'],
3052
+ elasticsearch: ['database-design', 'data-architecture'],
3053
+ kafka: ['distributed-systems', 'data-architecture'],
3054
+ rabbitmq: ['distributed-systems', 'microservices'],
3055
+ aws: ['cloud-architecture', 'scalability'],
3056
+ azure: ['cloud-architecture', 'scalability'],
3057
+ gcp: ['cloud-architecture', 'scalability'],
3058
+ terraform: ['infrastructure-as-code', 'cloud-architecture'],
3059
+ ansible: ['infrastructure-as-code', 'automation'],
3060
+ jenkins: ['ci-cd', 'automation'],
3061
+ 'github-actions': ['ci-cd', 'automation'],
3062
+ 'gitlab-ci': ['ci-cd', 'automation'],
3063
+ };
3064
+ // Collect domains based on technology focus
3065
+ const technologyDomains = new Set();
3066
+ for (const tech of technologyFocus) {
3067
+ const techLower = tech.toLowerCase();
3068
+ const domains = technologyDomainMap[techLower];
3069
+ if (domains) {
3070
+ domains.forEach(domain => technologyDomains.add(domain));
3071
+ }
3072
+ }
3073
+ // Combine base domains with technology-specific domains
3074
+ const allDomains = [...baseDomains, ...Array.from(technologyDomains)];
3075
+ // Remove duplicates and limit to reasonable number
3076
+ const uniqueDomains = [...new Set(allDomains)];
3077
+ // Return up to 6 most relevant domains
3078
+ return uniqueDomains.slice(0, 6);
3079
+ }
3080
+ /**
3081
+ * Helper method to create base ADR generation prompt
3082
+ */
3083
+ createBaseAdrPrompt(prdPath, outputDirectory, knowledgeContext) {
3084
+ return `
3085
+ # Enhanced ADR Generation from PRD Request
3086
+
3087
+ This is a comprehensive prompt-driven ADR generation process enhanced with domain knowledge and optimized prompting.
3088
+
3089
+ ${knowledgeContext}
3090
+
3091
+ ## Step 1: File Validation
3092
+ Please verify that the PRD file exists at: ${prdPath}
3093
+
3094
+ ## Step 2: PRD Content Reading
3095
+ Read and analyze the PRD content from: ${prdPath}
3096
+
3097
+ ## Step 3: Enhanced ADR Generation and Creation
3098
+
3099
+ Once you have successfully read the PRD content, analyze it using the domain knowledge above and generate Architectural Decision Records (ADRs).
3100
+
3101
+ ### Enhanced Analysis Requirements
3102
+
3103
+ 1. **Extract Key Decisions**: Identify all architectural decisions implied or stated in the PRD
3104
+ 2. **Apply Domain Knowledge**: Use the generated domain knowledge to enhance decision analysis
3105
+ 3. **Decision Categorization**: Group decisions by:
3106
+ - Technology stack choices (informed by domain best practices)
3107
+ - Architectural patterns (leveraging domain-specific patterns)
3108
+ - Infrastructure decisions (considering domain requirements)
3109
+ - Security considerations (applying domain security knowledge)
3110
+ - Performance requirements (using domain performance insights)
3111
+ - Integration approaches (following domain integration patterns)
3112
+
3113
+ ### Enhanced ADR Generation Requirements
3114
+
3115
+ 1. **Follow ADR Format**: Use standard ADR template with domain-enhanced content
3116
+ 2. **Number Sequentially**: Use format 001-decision-title.md, 002-next-decision.md, etc.
3117
+ 3. **Output Directory**: Place ADRs in ${outputDirectory}/
3118
+ 4. **Domain Context**: Include relevant domain knowledge in each ADR
3119
+ 5. **File Creation**: Generate file creation prompts for each ADR
3120
+
3121
+ ### Enhanced ADR Template Format
3122
+
3123
+ \`\`\`markdown
3124
+ # [Number]. [Title]
3125
+
3126
+ **Status**: [Proposed/Accepted/Deprecated/Superseded]
3127
+ **Date**: [YYYY-MM-DD]
3128
+ **Domain**: [Relevant domain from knowledge enhancement]
3129
+
3130
+ ## Context
3131
+ [Describe the context and problem statement from PRD, enhanced with domain knowledge]
3132
+
3133
+ ## Decision
3134
+ [Describe the architectural decision, informed by domain best practices]
3135
+
3136
+ ## Consequences
3137
+ [Describe positive and negative consequences, considering domain-specific implications]
3138
+
3139
+ ## Domain Considerations
3140
+ [Specific considerations from the domain knowledge that influenced this decision]
3141
+
3142
+ ## Implementation Plan
3143
+ [Steps to implement this decision, leveraging domain expertise]
3144
+
3145
+ ## Related PRD Sections
3146
+ [Reference specific sections from the PRD that led to this decision]
3147
+
3148
+ ## Domain References
3149
+ [References to domain knowledge that informed this decision]
3150
+ \`\`\`
3151
+
3152
+ ### Expected Enhanced Output
3153
+
3154
+ Please provide:
3155
+ 1. **File Validation Results**: Confirmation that PRD file exists and is readable
3156
+ 2. **PRD Content Summary**: Brief summary enhanced with domain context
3157
+ 3. **Domain Analysis**: How domain knowledge applies to this PRD
3158
+ 4. **Identified Decisions**: List of all architectural decisions with domain context
3159
+ 5. **Generated ADRs**: Complete enhanced ADR content for each decision
3160
+ 6. **File Creation Plan**: File names, directory structure, and creation order
3161
+ 7. **Implementation Priority**: Recommended order considering domain best practices
3162
+
3163
+ ### Quality Assurance with Domain Enhancement
3164
+
3165
+ - Ensure each ADR leverages relevant domain knowledge
3166
+ - Verify decisions align with domain best practices
3167
+ - Check that domain considerations are properly documented
3168
+ - Validate that ADR content is enhanced beyond basic analysis
3169
+ `;
3170
+ }
3171
+ /**
3172
+ * ADR suggestion tool implementations
3173
+ */
3174
+ async suggestAdrs(args) {
3175
+ const { suggestAdrs } = await import('./tools/adr-suggestion-tool.js');
3176
+ return await suggestAdrs(args);
3177
+ }
3178
+ async generateAdrFromDecision(args) {
3179
+ const { generateAdrFromDecision } = await import('./tools/adr-suggestion-tool.js');
3180
+ return await generateAdrFromDecision(args);
3181
+ }
3182
+ async generateAdrBootstrap(args) {
3183
+ const { default: generateAdrBootstrapScripts } = await import('./tools/adr-bootstrap-validation-tool.js');
3184
+ return await generateAdrBootstrapScripts(args);
3185
+ }
3186
+ async bootstrapValidationLoop(args) {
3187
+ const { default: bootstrapValidationLoop } = await import('./tools/bootstrap-validation-loop-tool.js');
3188
+ return await bootstrapValidationLoop(args);
3189
+ }
3190
+ async discoverExistingAdrs(args, context) {
3191
+ const ctx = context || createNoOpContext();
3192
+ try {
3193
+ ctx.info('🔍 Starting ADR discovery process...');
3194
+ ctx.report_progress(0, 100);
3195
+ ctx.info('📂 Phase 1: Scanning ADR directory');
3196
+ ctx.report_progress(30, 100);
3197
+ const { discoverExistingAdrs } = await import('./tools/adr-suggestion-tool.js');
3198
+ ctx.info('📄 Phase 2: Analyzing ADR files');
3199
+ ctx.report_progress(60, 100);
3200
+ const result = await discoverExistingAdrs(args);
3201
+ ctx.info('✅ ADR discovery completed successfully');
3202
+ ctx.report_progress(100, 100);
3203
+ return result;
3204
+ }
3205
+ catch (error) {
3206
+ ctx.error?.(`❌ ADR discovery failed: ${error instanceof Error ? error.message : String(error)}`);
3207
+ throw error;
3208
+ }
3209
+ }
3210
+ async analyzeAdrTimeline(args) {
3211
+ try {
3212
+ const projectPath = args['projectPath'] || this.config.projectPath;
3213
+ const adrDirectory = args['adrDirectory'] || 'docs/adrs';
3214
+ const generateActions = args['generateActions'] ?? true;
3215
+ const thresholdProfile = args['thresholdProfile'];
3216
+ const autoDetectContext = args['autoDetectContext'] ?? true;
3217
+ const includeContent = args['includeContent'] ?? true;
3218
+ const forceExtract = args['forceExtract'] ?? false;
3219
+ const { discoverAdrsInDirectory } = await import('./utils/adr-discovery.js');
3220
+ const { formatActionReport } = await import('./utils/adr-action-analyzer.js');
3221
+ // Discover ADRs with timeline analysis
3222
+ const result = await discoverAdrsInDirectory(adrDirectory, projectPath, {
3223
+ includeContent,
3224
+ includeTimeline: true,
3225
+ timelineOptions: {
3226
+ forceExtract,
3227
+ useCache: true,
3228
+ cacheTTL: 3600,
3229
+ },
3230
+ generateActions,
3231
+ ...(thresholdProfile ? { thresholdProfile } : {}),
3232
+ autoDetectContext,
3233
+ });
3234
+ // Format response
3235
+ let responseText = `# ADR Timeline Analysis\n\n`;
3236
+ responseText += `**Project:** ${projectPath}\n`;
3237
+ responseText += `**ADR Directory:** ${adrDirectory}\n`;
3238
+ responseText += `**Total ADRs:** ${result.totalAdrs}\n\n`;
3239
+ // Add timeline summary
3240
+ if (result.adrs.some(adr => adr.timeline)) {
3241
+ const withTimeline = result.adrs.filter(adr => adr.timeline).length;
3242
+ responseText += `## Timeline Data\n\n`;
3243
+ responseText += `- **ADRs with Timeline:** ${withTimeline}/${result.totalAdrs}\n`;
3244
+ const ages = result.adrs.filter(adr => adr.timeline).map(adr => adr.timeline.age_days);
3245
+ if (ages.length > 0) {
3246
+ const avgAge = Math.floor(ages.reduce((a, b) => a + b, 0) / ages.length);
3247
+ const oldestAge = Math.max(...ages);
3248
+ responseText += `- **Average ADR Age:** ${avgAge} days\n`;
3249
+ responseText += `- **Oldest ADR:** ${oldestAge} days\n`;
3250
+ }
3251
+ responseText += `\n`;
3252
+ }
3253
+ // Add action queue report
3254
+ if (result.actionQueue) {
3255
+ responseText += `---\n\n`;
3256
+ responseText += formatActionReport(result.actionQueue, {
3257
+ projectPath,
3258
+ thresholdProfile: thresholdProfile || 'auto-detected',
3259
+ });
3260
+ }
3261
+ else if (generateActions) {
3262
+ responseText += `## No Actions Required\n\n`;
3263
+ responseText += `All ADRs are up to date and within acceptable thresholds.\n`;
3264
+ }
3265
+ // Add summary stats
3266
+ if (result.summary.byStatus) {
3267
+ responseText += `\n---\n\n## ADR Status Distribution\n\n`;
3268
+ Object.entries(result.summary.byStatus).forEach(([status, count]) => {
3269
+ responseText += `- **${status}:** ${count}\n`;
3270
+ });
3271
+ }
3272
+ return {
3273
+ content: [
3274
+ {
3275
+ type: 'text',
3276
+ text: responseText,
3277
+ },
3278
+ ],
3279
+ };
3280
+ }
3281
+ catch (error) {
3282
+ return {
3283
+ content: [
3284
+ {
3285
+ type: 'text',
3286
+ text: `# ADR Timeline Analysis Failed\n\n**Error:** ${error instanceof Error ? error.message : String(error)}\n\nPlease check that the ADR directory exists and contains valid ADR files.`,
3287
+ },
3288
+ ],
3289
+ isError: true,
3290
+ };
3291
+ }
3292
+ }
3293
+ async reviewExistingAdrs(args) {
3294
+ const { reviewExistingAdrs } = await import('./tools/review-existing-adrs-tool.js');
3295
+ return await reviewExistingAdrs(args);
3296
+ }
3297
+ /**
3298
+ * ADR validation tool implementations
3299
+ */
3300
+ async validateAdr(args) {
3301
+ const { validateAdr } = await import('./tools/adr-validation-tool.js');
3302
+ return await validateAdr(args);
3303
+ }
3304
+ async validateAllAdrs(args) {
3305
+ const { validateAllAdrs } = await import('./tools/adr-validation-tool.js');
3306
+ return await validateAllAdrs(args);
3307
+ }
3308
+ /**
3309
+ * Research integration tool implementations
3310
+ */
3311
+ async incorporateResearch(args) {
3312
+ const { incorporateResearch } = await import('./tools/research-integration-tool.js');
3313
+ return await incorporateResearch(args);
3314
+ }
3315
+ async createResearchTemplate(args) {
3316
+ const { createResearchTemplate } = await import('./tools/research-integration-tool.js');
3317
+ return await createResearchTemplate(args);
3318
+ }
3319
+ async requestActionConfirmation(args) {
3320
+ const { requestActionConfirmation } = await import('./tools/research-integration-tool.js');
3321
+ return await requestActionConfirmation(args);
3322
+ }
3323
+ /**
3324
+ * Rule generation and validation tool implementations
3325
+ */
3326
+ async generateRules(args) {
3327
+ const { generateRules } = await import('./tools/rule-generation-tool.js');
3328
+ return await generateRules(args);
3329
+ }
3330
+ async validateRules(args) {
3331
+ const { validateRules } = await import('./tools/rule-generation-tool.js');
3332
+ return await validateRules(args);
3333
+ }
3334
+ async createRuleSet(args) {
3335
+ const { createRuleSet } = await import('./tools/rule-generation-tool.js');
3336
+ return await createRuleSet(args);
3337
+ }
3338
+ /**
3339
+ * Environment analysis tool implementation
3340
+ */
3341
+ async analyzeEnvironment(args) {
3342
+ const { analyzeEnvironment } = await import('./tools/environment-analysis-tool.js');
3343
+ return await analyzeEnvironment(args);
3344
+ }
3345
+ /**
3346
+ * Research question generation tool implementation
3347
+ */
3348
+ async generateResearchQuestions(args) {
3349
+ const { generateResearchQuestions } = await import('./tools/research-question-tool.js');
3350
+ return await generateResearchQuestions(args);
3351
+ }
3352
+ /**
3353
+ * Perform research tool implementation
3354
+ */
3355
+ async performResearch(args, context) {
3356
+ const ctx = context || createNoOpContext();
3357
+ if (!('question' in args) || typeof args['question'] !== 'string') {
3358
+ throw new McpAdrError('Missing required parameter: question', 'INVALID_ARGUMENTS');
3359
+ }
3360
+ try {
3361
+ ctx.info('🔍 Starting research process...');
3362
+ ctx.report_progress(0, 100);
3363
+ ctx.info('📊 Phase 1: Initializing research framework');
3364
+ ctx.report_progress(10, 100);
3365
+ const { performResearch } = await import('./tools/perform-research-tool.js');
3366
+ ctx.info('📚 Phase 2: Executing research orchestration');
3367
+ ctx.report_progress(20, 100);
3368
+ const result = await performResearch(args, ctx // ✅ Pass context to tool function for progress updates
3369
+ );
3370
+ return result;
3371
+ }
3372
+ catch (error) {
3373
+ ctx.error?.(`❌ Research execution failed: ${error instanceof Error ? error.message : String(error)}`);
3374
+ throw new McpAdrError(`Failed to perform research: ${error instanceof Error ? error.message : String(error)}`, 'RESEARCH_EXECUTION_ERROR');
3375
+ }
3376
+ }
3377
+ /**
3378
+ * Search codebase tool implementation
3379
+ */
3380
+ async searchCodebase(args) {
3381
+ if (!('query' in args) || typeof args['query'] !== 'string') {
3382
+ throw new McpAdrError('Missing required parameter: query', 'INVALID_ARGUMENTS');
3383
+ }
3384
+ try {
3385
+ const { searchCodebaseTool } = await import('./tools/search-codebase-tool.js');
3386
+ return await searchCodebaseTool(args);
3387
+ }
3388
+ catch (error) {
3389
+ throw new McpAdrError(`Failed to search codebase: ${error instanceof Error ? error.message : String(error)}`, 'SEARCH_ERROR');
3390
+ }
3391
+ }
3392
+ /**
3393
+ * Deployment analysis tool implementation
3394
+ */
3395
+ async analyzeDeploymentProgress(args) {
3396
+ const { analyzeDeploymentProgress } = await import('./tools/deployment-analysis-tool.js');
3397
+ return await analyzeDeploymentProgress(args);
3398
+ }
3399
+ /**
3400
+ * Apply content masking to MCP response
3401
+ */
3402
+ /**
3403
+ * Track memory operations performed by tools
3404
+ */
3405
+ async trackMemoryOperations(toolName, parameters, result, success) {
3406
+ try {
3407
+ // Check if memory integration was enabled and used
3408
+ if (parameters?.enableMemoryIntegration === false) {
3409
+ return; // Memory integration was explicitly disabled
3410
+ }
3411
+ // Extract memory operation information from result
3412
+ const memoryOps = this.extractMemoryOperations(toolName, parameters, result);
3413
+ if (memoryOps.length > 0) {
3414
+ // Store memory operation tracking in knowledge graph
3415
+ for (const op of memoryOps) {
3416
+ await this.kgManager.addMemoryExecution(toolName, op.action, op.entityType, success && op.success, op.details);
3417
+ }
3418
+ }
3419
+ }
3420
+ catch (error) {
3421
+ // Don't let memory tracking errors break execution
3422
+ console.error('[WARN] Memory operation tracking failed:', error);
3423
+ }
3424
+ }
3425
+ /**
3426
+ * Extract memory operation details from tool execution
3427
+ */
3428
+ extractMemoryOperations(toolName, parameters, result) {
3429
+ const operations = [];
3430
+ // Define memory-enabled tools and their expected operations
3431
+ const memoryEnabledTools = {
3432
+ analyze_content_security: {
3433
+ entityType: 'security_pattern',
3434
+ actions: ['store_pattern', 'analyze_institutional_security', 'track_evolution'],
3435
+ },
3436
+ analyze_environment: {
3437
+ entityType: 'environment_snapshot',
3438
+ actions: ['store_snapshot', 'analyze_trends', 'compare_configurations'],
3439
+ },
3440
+ deployment_readiness: {
3441
+ entityType: 'deployment_assessment',
3442
+ actions: ['store_assessment', 'migrate_history', 'analyze_patterns'],
3443
+ },
3444
+ troubleshoot_guided_workflow: {
3445
+ entityType: 'troubleshooting_session',
3446
+ actions: ['store_session', 'pattern_recognition', 'suggest_adrs', 'generate_research'],
3447
+ },
3448
+ };
3449
+ // Check if this tool supports memory operations
3450
+ const toolConfig = memoryEnabledTools[toolName];
3451
+ if (!toolConfig) {
3452
+ return operations; // Tool doesn't support memory operations
3453
+ }
3454
+ // Extract memory operation details from result
3455
+ if (result?.memoryIntegration) {
3456
+ const memoryInfo = result.memoryIntegration;
3457
+ // Pattern entity storage operation
3458
+ if (memoryInfo.entityStored || memoryInfo.patternStored) {
3459
+ operations.push({
3460
+ action: 'entity_storage',
3461
+ entityType: toolConfig.entityType,
3462
+ success: memoryInfo.storageSuccess !== false,
3463
+ details: {
3464
+ entityId: memoryInfo.entityId || memoryInfo.patternId,
3465
+ entityCount: memoryInfo.entityCount || 1,
3466
+ storageMethod: memoryInfo.storageMethod || 'standard',
3467
+ },
3468
+ });
3469
+ }
3470
+ // Historical analysis operation
3471
+ if (memoryInfo.historicalAnalysis || memoryInfo.trendAnalysis) {
3472
+ operations.push({
3473
+ action: 'historical_analysis',
3474
+ entityType: toolConfig.entityType,
3475
+ success: memoryInfo.analysisSuccess !== false,
3476
+ details: {
3477
+ analysisType: memoryInfo.analysisType || 'trend_analysis',
3478
+ entitiesAnalyzed: memoryInfo.entitiesAnalyzed || 0,
3479
+ insights: memoryInfo.insights || [],
3480
+ },
3481
+ });
3482
+ }
3483
+ // Evolution tracking operation
3484
+ if (memoryInfo.evolutionTracking) {
3485
+ operations.push({
3486
+ action: 'evolution_tracking',
3487
+ entityType: toolConfig.entityType,
3488
+ success: memoryInfo.evolutionSuccess !== false,
3489
+ details: {
3490
+ improvements: memoryInfo.improvements || [],
3491
+ degradations: memoryInfo.degradations || [],
3492
+ recommendations: memoryInfo.recommendations || [],
3493
+ },
3494
+ });
3495
+ }
3496
+ // Migration operation (for deployment readiness)
3497
+ if (memoryInfo.migrationCompleted) {
3498
+ operations.push({
3499
+ action: 'data_migration',
3500
+ entityType: toolConfig.entityType,
3501
+ success: memoryInfo.migrationSuccess !== false,
3502
+ details: {
3503
+ migratedRecords: memoryInfo.migratedRecords || 0,
3504
+ migrationMethod: memoryInfo.migrationMethod || 'json_to_memory',
3505
+ },
3506
+ });
3507
+ }
3508
+ }
3509
+ // If no specific memory integration info, infer from parameters
3510
+ if (operations.length === 0 && parameters?.enableMemoryIntegration !== false) {
3511
+ // Default assumption: entity was stored
3512
+ operations.push({
3513
+ action: 'entity_storage',
3514
+ entityType: toolConfig.entityType,
3515
+ success: true, // Assume success if no explicit info
3516
+ details: {
3517
+ entityCount: 1,
3518
+ storageMethod: 'inferred',
3519
+ note: 'Memory operation inferred from tool execution',
3520
+ },
3521
+ });
3522
+ }
3523
+ return operations;
3524
+ }
3525
+ /**
3526
+ * Track tool execution in knowledge graph
3527
+ */
3528
+ async trackToolExecution(toolName, parameters, result, success, error) {
3529
+ try {
3530
+ // Extract intentId from metadata if available
3531
+ let intentId;
3532
+ if (result?.metadata?.intentId) {
3533
+ intentId = result.metadata.intentId;
3534
+ }
3535
+ else {
3536
+ // Check for active intents that might be related to this tool execution
3537
+ const activeIntents = await this.kgManager.getActiveIntents();
3538
+ if (activeIntents.length > 0) {
3539
+ // Use the most recent active intent
3540
+ const latestIntent = activeIntents[activeIntents.length - 1];
3541
+ if (latestIntent) {
3542
+ intentId = latestIntent.intentId;
3543
+ }
3544
+ }
3545
+ }
3546
+ // If no intent found, create a standalone execution record
3547
+ if (!intentId) {
3548
+ // Extract human request from conversation context if available
3549
+ let humanRequest = `Standalone tool execution: ${toolName}`;
3550
+ if (parameters?.conversationContext?.humanRequest) {
3551
+ humanRequest = parameters.conversationContext.humanRequest;
3552
+ }
3553
+ intentId = await this.kgManager.createIntent(humanRequest, [`Execute ${toolName}`, 'Complete tool operation'], 'medium');
3554
+ }
3555
+ // Determine tasks created/modified from tool operation
3556
+ const todoTasksCreated = [];
3557
+ const todoTasksModified = [];
3558
+ // Extract task information from result metadata
3559
+ if (result?.metadata) {
3560
+ if (result.metadata.tasksCreated) {
3561
+ todoTasksCreated.push(...result.metadata.tasksCreated);
3562
+ }
3563
+ if (result.metadata.tasksModified) {
3564
+ todoTasksModified.push(...result.metadata.tasksModified);
3565
+ }
3566
+ if (result.metadata.taskIds) {
3567
+ todoTasksModified.push(...result.metadata.taskIds);
3568
+ }
3569
+ }
3570
+ // Track memory operations if present
3571
+ await this.trackMemoryOperations(toolName, parameters, result, success);
3572
+ // Store execution in knowledge graph
3573
+ await this.kgManager.addToolExecution(intentId, toolName, parameters, result, success, todoTasksCreated, todoTasksModified, error);
3574
+ // If execution completed successfully, update intent status
3575
+ if (success && !error) {
3576
+ // Check if this might be the final tool in a chain
3577
+ const intent = await this.kgManager.getIntentById(intentId);
3578
+ if (intent && intent.currentStatus === 'executing') {
3579
+ // Simple heuristic: if tool is a "completion" type tool, mark intent as completed
3580
+ const completionTools = ['smart_git_push', 'generate_deployment_guidance', 'smart_score'];
3581
+ if (completionTools.includes(toolName)) {
3582
+ await this.kgManager.updateIntentStatus(intentId, 'completed');
3583
+ }
3584
+ }
3585
+ }
3586
+ }
3587
+ catch (trackingError) {
3588
+ // Don't let tracking errors break tool execution
3589
+ console.error('[WARN] Knowledge graph tracking failed:', trackingError);
3590
+ }
3591
+ }
3592
+ async applyOutputMasking(response) {
3593
+ try {
3594
+ return await maskMcpResponse(response, this.maskingConfig);
3595
+ }
3596
+ catch (error) {
3597
+ // If masking fails, log warning and return original response
3598
+ // Log to stderr to avoid corrupting MCP protocol
3599
+ console.error('[WARN] Output masking failed:', error);
3600
+ return response;
3601
+ }
3602
+ }
3603
+ /**
3604
+ * Enrich response with state reinforcement and apply masking
3605
+ *
3606
+ * Implements Phase 2 of context decay mitigation by injecting
3607
+ * context reminders every N turns or when response exceeds token threshold.
3608
+ *
3609
+ * Phase 3 extension: Records conversation turns to structured external memory.
3610
+ */
3611
+ async enrichResponseWithStateReinforcement(response, toolName, toolArgs) {
3612
+ const startTime = Date.now();
3613
+ try {
3614
+ // Extract text content from response
3615
+ const textContent = response.content
3616
+ .filter((item) => item.type === 'text')
3617
+ .map(item => item.text)
3618
+ .join('\n\n');
3619
+ if (!textContent) {
3620
+ // No text content to enrich, just apply masking
3621
+ return await this.applyOutputMasking(response);
3622
+ }
3623
+ // Enrich with state reinforcement (Phase 2)
3624
+ const enriched = await this.stateReinforcementManager.enrichResponseWithContext(textContent);
3625
+ // Prepare final response
3626
+ let finalResponse;
3627
+ // Replace text content with enriched version if context was injected
3628
+ if (enriched.contextInjected) {
3629
+ finalResponse = {
3630
+ ...response,
3631
+ content: response.content.map(item => {
3632
+ if (item.type === 'text') {
3633
+ return {
3634
+ type: 'text',
3635
+ text: enriched.enrichedContent,
3636
+ };
3637
+ }
3638
+ return item;
3639
+ }),
3640
+ };
3641
+ }
3642
+ else {
3643
+ finalResponse = response;
3644
+ }
3645
+ // Record conversation turn (Phase 3: Structured External Memory)
3646
+ if (toolName) {
3647
+ const duration = Date.now() - startTime;
3648
+ // Check if response has expandableId (from tiered response)
3649
+ const expandableIdMatch = textContent.match(/expandableId:\s*(\S+)/);
3650
+ const expandableId = expandableIdMatch ? expandableIdMatch[1] : undefined;
3651
+ await this.conversationMemoryManager.recordTurn({
3652
+ type: 'tool_call',
3653
+ toolName,
3654
+ toolArgs,
3655
+ }, {
3656
+ content: enriched.enrichedContent || textContent,
3657
+ tokenCount: enriched.tokenCount,
3658
+ contextInjected: enriched.contextInjected,
3659
+ ...(expandableId ? { expandableId } : {}),
3660
+ }, {
3661
+ duration,
3662
+ cacheHit: false, // Could be enhanced to track cache hits
3663
+ errorOccurred: false,
3664
+ });
3665
+ this.logger.debug(`Conversation turn recorded for ${toolName}`, 'McpAdrAnalysisServer', {
3666
+ turnNumber: enriched.turnNumber,
3667
+ });
3668
+ }
3669
+ // Apply masking to final response
3670
+ return await this.applyOutputMasking(finalResponse);
3671
+ }
3672
+ catch (error) {
3673
+ this.logger.error('State reinforcement or conversation recording failed, returning original response', 'McpAdrAnalysisServer', error instanceof Error ? error : undefined);
3674
+ // Fallback to just masking if enrichment fails
3675
+ return await this.applyOutputMasking(response);
3676
+ }
3677
+ }
3678
+ /**
3679
+ * Read MCP resource with prompt-driven caching
3680
+ */
3681
+ async readResource(uri) {
3682
+ try {
3683
+ // Import resource router and templated resources (ensures routes are registered)
3684
+ const { resourceRouter } = await import('./resources/resource-router.js');
3685
+ // Import templated resources to register routes
3686
+ await import('./resources/adr-by-id-resource.js');
3687
+ await import('./resources/research-by-topic-resource.js');
3688
+ await import('./resources/todo-by-id-resource.js');
3689
+ await import('./resources/rule-by-id-resource.js');
3690
+ await import('./resources/technology-by-name-resource.js');
3691
+ await import('./resources/pattern-by-name-resource.js');
3692
+ await import('./resources/validated-pattern-by-platform-resource.js');
3693
+ await import('./resources/pattern-sources-by-platform-resource.js');
3694
+ await import('./resources/pattern-base-code-by-platform-resource.js');
3695
+ // Phase 1 & 2 resources (PR #346)
3696
+ await import('./resources/server-context-resource.js');
3697
+ await import('./resources/memory-stats-resource.js');
3698
+ await import('./resources/conversation-snapshot-resource.js');
3699
+ await import('./resources/tool-catalog-resource.js');
3700
+ await import('./resources/adrs-discovered-resource.js');
3701
+ // Knowledge Graph Resource (ADR-018)
3702
+ const { generateKnowledgeGraphResource } = await import('./resources/knowledge-graph-resource.js');
3703
+ // Handle knowledge://graph specially to inject KnowledgeGraphManager
3704
+ if (uri === 'knowledge://graph') {
3705
+ const url = new globalThis.URL(uri);
3706
+ const result = await generateKnowledgeGraphResource({}, url.searchParams, this.kgManager);
3707
+ return {
3708
+ contents: [
3709
+ {
3710
+ uri,
3711
+ mimeType: result.contentType,
3712
+ text: JSON.stringify(result.data, null, 2),
3713
+ },
3714
+ ],
3715
+ _meta: {
3716
+ lastModified: result.lastModified,
3717
+ etag: result.etag,
3718
+ cacheKey: result.cacheKey,
3719
+ },
3720
+ };
3721
+ }
3722
+ // Try routing first (handles templated resources)
3723
+ if (resourceRouter.canRoute(uri)) {
3724
+ const result = await resourceRouter.route(uri);
3725
+ return {
3726
+ contents: [
3727
+ {
3728
+ uri,
3729
+ mimeType: result.contentType,
3730
+ text: JSON.stringify(result.data, null, 2),
3731
+ },
3732
+ ],
3733
+ _meta: {
3734
+ lastModified: result.lastModified,
3735
+ etag: result.etag,
3736
+ cacheKey: result.cacheKey,
3737
+ },
3738
+ };
3739
+ }
3740
+ // Fall back to static resource handling
3741
+ // Parse URI to determine resource type and parameters
3742
+ const url = new globalThis.URL(uri);
3743
+ // For a non-special scheme like `adr://adr_list`, WHATWG URL puts the name in
3744
+ // `host`, not `pathname` -- pathname is ''. Reading pathname alone made every one
3745
+ // of the 16 cases below unreachable: resourceType was always '', so the switch fell
3746
+ // straight to `default` and threw "Unknown resource type: " with nothing after the
3747
+ // colon. 16 of the 17 concrete resources advertised in resources/list were dead.
3748
+ //
3749
+ // adr://adr_list -> host 'adr_list', pathname ''
3750
+ // adr://adr/{id} -> host 'adr', pathname '/%7Bid%7D'
3751
+ //
3752
+ // Prefer the host; fall back to pathname so path-style URIs still resolve.
3753
+ const resourceType = url.host || url.pathname.replace('/', '');
3754
+ const params = Object.fromEntries(url.searchParams.entries());
3755
+ switch (resourceType) {
3756
+ case 'architectural_knowledge_graph': {
3757
+ const { generateArchitecturalKnowledgeGraph } = await import('./resources/index.js');
3758
+ const projectPath = params['projectPath'] || process.cwd();
3759
+ // Generate resource directly (caching is now handled through AI delegation)
3760
+ const result = await generateArchitecturalKnowledgeGraph(projectPath);
3761
+ return {
3762
+ contents: [
3763
+ {
3764
+ uri,
3765
+ mimeType: result.contentType,
3766
+ text: JSON.stringify(result.data, null, 2),
3767
+ },
3768
+ ],
3769
+ };
3770
+ }
3771
+ case 'analysis_report': {
3772
+ const { generateAnalysisReport } = await import('./resources/index.js');
3773
+ const projectPath = params['projectPath'] || process.cwd();
3774
+ const focusAreas = params['focusAreas'] ? params['focusAreas'].split(',') : undefined;
3775
+ // Generate resource directly (caching is now handled through AI delegation)
3776
+ const result = await generateAnalysisReport(projectPath, focusAreas);
3777
+ return {
3778
+ contents: [
3779
+ {
3780
+ uri,
3781
+ mimeType: result.contentType,
3782
+ text: JSON.stringify(result.data, null, 2),
3783
+ },
3784
+ ],
3785
+ };
3786
+ }
3787
+ case 'adr_list': {
3788
+ const { generateAdrList } = await import('./resources/index.js');
3789
+ const { getAdrDirectoryPath } = await import('./utils/config.js');
3790
+ const path = await import('path');
3791
+ // Use absolute ADR path relative to project
3792
+ const absoluteAdrPath = params['adrDirectory']
3793
+ ? path.resolve(this.config.projectPath, params['adrDirectory'])
3794
+ : getAdrDirectoryPath(this.config);
3795
+ // Generate resource directly (caching is now handled through AI delegation)
3796
+ const result = await generateAdrList(absoluteAdrPath, this.config.projectPath);
3797
+ return {
3798
+ contents: [
3799
+ {
3800
+ uri,
3801
+ mimeType: result.contentType,
3802
+ text: JSON.stringify(result.data, null, 2),
3803
+ },
3804
+ ],
3805
+ };
3806
+ }
3807
+ case 'todo_list': {
3808
+ const { generateTodoListResource } = await import('./resources/todo-list-resource.js');
3809
+ const result = await generateTodoListResource();
3810
+ return {
3811
+ contents: [
3812
+ {
3813
+ uri,
3814
+ mimeType: result.contentType,
3815
+ text: JSON.stringify(result.data, null, 2),
3816
+ },
3817
+ ],
3818
+ _meta: {
3819
+ lastModified: result.lastModified,
3820
+ etag: result.etag,
3821
+ cacheKey: result.cacheKey,
3822
+ },
3823
+ };
3824
+ }
3825
+ case 'research_index': {
3826
+ const { generateResearchIndexResource } = await import('./resources/research-index-resource.js');
3827
+ const result = await generateResearchIndexResource();
3828
+ return {
3829
+ contents: [
3830
+ {
3831
+ uri,
3832
+ mimeType: result.contentType,
3833
+ text: JSON.stringify(result.data, null, 2),
3834
+ },
3835
+ ],
3836
+ _meta: {
3837
+ lastModified: result.lastModified,
3838
+ etag: result.etag,
3839
+ cacheKey: result.cacheKey,
3840
+ },
3841
+ };
3842
+ }
3843
+ case 'rule_catalog': {
3844
+ const { generateRuleCatalogResource } = await import('./resources/rule-catalog-resource.js');
3845
+ const result = await generateRuleCatalogResource();
3846
+ return {
3847
+ contents: [
3848
+ {
3849
+ uri,
3850
+ mimeType: result.contentType,
3851
+ text: JSON.stringify(result.data, null, 2),
3852
+ },
3853
+ ],
3854
+ _meta: {
3855
+ lastModified: result.lastModified,
3856
+ etag: result.etag,
3857
+ cacheKey: result.cacheKey,
3858
+ },
3859
+ };
3860
+ }
3861
+ case 'rule_generation': {
3862
+ const { generateRuleGenerationResource } = await import('./resources/rule-generation-resource.js');
3863
+ const result = await generateRuleGenerationResource(undefined, url.searchParams);
3864
+ return {
3865
+ contents: [
3866
+ {
3867
+ uri,
3868
+ mimeType: result.contentType,
3869
+ text: JSON.stringify(result.data, null, 2),
3870
+ },
3871
+ ],
3872
+ _meta: {
3873
+ lastModified: result.lastModified,
3874
+ etag: result.etag,
3875
+ cacheKey: result.cacheKey,
3876
+ },
3877
+ };
3878
+ }
3879
+ case 'project_status': {
3880
+ const { generateProjectStatusResource } = await import('./resources/project-status-resource.js');
3881
+ const result = await generateProjectStatusResource();
3882
+ return {
3883
+ contents: [
3884
+ {
3885
+ uri,
3886
+ mimeType: result.contentType,
3887
+ text: JSON.stringify(result.data, null, 2),
3888
+ },
3889
+ ],
3890
+ _meta: {
3891
+ lastModified: result.lastModified,
3892
+ etag: result.etag,
3893
+ cacheKey: result.cacheKey,
3894
+ },
3895
+ };
3896
+ }
3897
+ case 'deployment_status': {
3898
+ const { generateDeploymentStatusResource } = await import('./resources/deployment-status-resource.js');
3899
+ const result = await generateDeploymentStatusResource(undefined, url.searchParams);
3900
+ return {
3901
+ contents: [
3902
+ {
3903
+ uri,
3904
+ mimeType: result.contentType,
3905
+ text: JSON.stringify(result.data, null, 2),
3906
+ },
3907
+ ],
3908
+ _meta: {
3909
+ lastModified: result.lastModified,
3910
+ etag: result.etag,
3911
+ cacheKey: result.cacheKey,
3912
+ },
3913
+ };
3914
+ }
3915
+ case 'environment_analysis': {
3916
+ const { generateEnvironmentAnalysisResource } = await import('./resources/environment-analysis-resource.js');
3917
+ const result = await generateEnvironmentAnalysisResource(undefined, url.searchParams);
3918
+ return {
3919
+ contents: [
3920
+ {
3921
+ uri,
3922
+ mimeType: result.contentType,
3923
+ text: JSON.stringify(result.data, null, 2),
3924
+ },
3925
+ ],
3926
+ _meta: {
3927
+ lastModified: result.lastModified,
3928
+ etag: result.etag,
3929
+ cacheKey: result.cacheKey,
3930
+ },
3931
+ };
3932
+ }
3933
+ case 'memory_snapshots': {
3934
+ const { generateMemorySnapshotsResource } = await import('./resources/memory-snapshots-resource.js');
3935
+ const result = await generateMemorySnapshotsResource(undefined, url.searchParams);
3936
+ return {
3937
+ contents: [
3938
+ {
3939
+ uri,
3940
+ mimeType: result.contentType,
3941
+ text: JSON.stringify(result.data, null, 2),
3942
+ },
3943
+ ],
3944
+ _meta: {
3945
+ lastModified: result.lastModified,
3946
+ etag: result.etag,
3947
+ cacheKey: result.cacheKey,
3948
+ },
3949
+ };
3950
+ }
3951
+ case 'project_metrics': {
3952
+ const { generateProjectMetricsResource } = await import('./resources/project-metrics-resource.js');
3953
+ const result = await generateProjectMetricsResource();
3954
+ return {
3955
+ contents: [
3956
+ {
3957
+ uri,
3958
+ mimeType: result.contentType,
3959
+ text: JSON.stringify(result.data, null, 2),
3960
+ },
3961
+ ],
3962
+ _meta: {
3963
+ lastModified: result.lastModified,
3964
+ etag: result.etag,
3965
+ cacheKey: result.cacheKey,
3966
+ },
3967
+ };
3968
+ }
3969
+ case 'deployment_history': {
3970
+ const { generateDeploymentHistoryResource } = await import('./resources/deployment-history-resource.js');
3971
+ const result = await generateDeploymentHistoryResource(undefined, url.searchParams);
3972
+ return {
3973
+ contents: [
3974
+ {
3975
+ uri,
3976
+ mimeType: result.contentType,
3977
+ text: JSON.stringify(result.data, null, 2),
3978
+ },
3979
+ ],
3980
+ _meta: {
3981
+ lastModified: result.lastModified,
3982
+ etag: result.etag,
3983
+ cacheKey: result.cacheKey,
3984
+ },
3985
+ };
3986
+ }
3987
+ case 'release_history': {
3988
+ const { generateReleaseHistoryResource } = await import('./resources/release-history-resource.js');
3989
+ const releaseProjectPath = process.env['PROJECT_PATH'] || process.cwd();
3990
+ const result = await generateReleaseHistoryResource(releaseProjectPath, url.searchParams);
3991
+ return {
3992
+ contents: [
3993
+ {
3994
+ uri,
3995
+ mimeType: result.contentType,
3996
+ text: JSON.stringify(result.data, null, 2),
3997
+ },
3998
+ ],
3999
+ _meta: {
4000
+ lastModified: result.lastModified,
4001
+ etag: result.etag,
4002
+ cacheKey: result.cacheKey,
4003
+ },
4004
+ };
4005
+ }
4006
+ case 'code_quality': {
4007
+ const { generateCodeQualityResource } = await import('./resources/code-quality-resource.js');
4008
+ const result = await generateCodeQualityResource(undefined, url.searchParams);
4009
+ return {
4010
+ contents: [
4011
+ {
4012
+ uri,
4013
+ mimeType: result.contentType,
4014
+ text: JSON.stringify(result.data, null, 2),
4015
+ },
4016
+ ],
4017
+ _meta: {
4018
+ lastModified: result.lastModified,
4019
+ etag: result.etag,
4020
+ cacheKey: result.cacheKey,
4021
+ },
4022
+ };
4023
+ }
4024
+ case 'validated_patterns': {
4025
+ const { generateValidatedPatternsCatalogResource } = await import('./resources/validated-patterns-catalog-resource.js');
4026
+ const result = await generateValidatedPatternsCatalogResource();
4027
+ return {
4028
+ contents: [
4029
+ {
4030
+ uri,
4031
+ mimeType: result.contentType,
4032
+ text: JSON.stringify(result.data, null, 2),
4033
+ },
4034
+ ],
4035
+ _meta: {
4036
+ lastModified: result.lastModified,
4037
+ etag: result.etag,
4038
+ cacheKey: result.cacheKey,
4039
+ },
4040
+ };
4041
+ }
4042
+ default:
4043
+ throw new McpAdrError(`Unknown resource type: ${resourceType}`, 'UNKNOWN_RESOURCE');
4044
+ }
4045
+ }
4046
+ catch (error) {
4047
+ if (error instanceof McpAdrError) {
4048
+ throw error;
4049
+ }
4050
+ throw new McpAdrError(`Failed to read resource: ${error instanceof Error ? error.message : String(error)}`, 'RESOURCE_ERROR');
4051
+ }
4052
+ }
4053
+ /**
4054
+ * Start the server
4055
+ */
4056
+ async start() {
4057
+ // Validate configuration before starting
4058
+ await this.validateConfiguration();
4059
+ // Initialize memory entity manager
4060
+ await this.memoryEntityManager.initialize();
4061
+ this.logger.info('Memory Entity Manager initialized', 'McpAdrAnalysisServer');
4062
+ // Initialize conversation memory manager (Phase 3: Structured External Memory)
4063
+ await this.conversationMemoryManager.initialize();
4064
+ this.logger.info('Phase 3 (Structured External Memory) initialized', 'McpAdrAnalysisServer');
4065
+ // Generate initial server context file
4066
+ try {
4067
+ await this.contextGenerator.writeContextFile(this.kgManager, this.memoryEntityManager, this.conversationMemoryManager);
4068
+ this.logger.info('Server context file generated at .mcp-server-context.md', 'McpAdrAnalysisServer');
4069
+ }
4070
+ catch (error) {
4071
+ this.logger.warn('Failed to generate initial server context file', 'McpAdrAnalysisServer', {
4072
+ error: error instanceof Error ? error.message : String(error),
4073
+ });
4074
+ }
4075
+ const transport = new StdioServerTransport();
4076
+ await this.server.connect(transport);
4077
+ // Keep the process alive
4078
+ process.on('SIGINT', async () => {
4079
+ await this.server.close();
4080
+ process.exit(0);
4081
+ });
4082
+ }
4083
+ /**
4084
+ * File system tool implementations
4085
+ */
4086
+ /**
4087
+ * List accessible roots (MCP best practice)
4088
+ */
4089
+ async listRoots() {
4090
+ const roots = this.rootManager.listRoots();
4091
+ const rootsList = roots
4092
+ .map(r => `### ${r.name}\n\n**Path**: \`${r.path}\`\n\n**Description**: ${r.description}\n`)
4093
+ .join('\n');
4094
+ return {
4095
+ content: [
4096
+ {
4097
+ type: 'text',
4098
+ text: `# Available File System Roots\n\nThese are the directories that can be accessed by this MCP server.\n\n${rootsList}\nUse these paths with \`read_directory\` and \`read_file\` tools to explore and access files.`,
4099
+ },
4100
+ ],
4101
+ };
4102
+ }
4103
+ /**
4104
+ * Read directory contents (MCP best practice for autonomous file discovery)
4105
+ */
4106
+ async readDirectory(args) {
4107
+ const targetPath = args.path || this.config.projectPath;
4108
+ try {
4109
+ const path = await import('path');
4110
+ const resolvedPath = path.resolve(targetPath);
4111
+ // Security check: ensure path is within accessible roots
4112
+ if (!this.rootManager.isPathAllowed(resolvedPath)) {
4113
+ const roots = this.rootManager.listRoots();
4114
+ const rootList = roots.map(r => ` - ${r.name}: ${r.path}`).join('\n');
4115
+ throw new McpAdrError(`Access denied: Path '${targetPath}' is outside accessible roots.\n\nAccessible roots:\n${rootList}\n\nUse list_roots tool for more details.`, 'ACCESS_DENIED');
4116
+ }
4117
+ const { readdir } = await import('fs/promises');
4118
+ const entries = await readdir(resolvedPath, { withFileTypes: true });
4119
+ const files = entries.filter(e => e.isFile()).map(e => `📄 ${e.name}`);
4120
+ const dirs = entries.filter(e => e.isDirectory()).map(e => `📁 ${e.name}/`);
4121
+ const root = this.rootManager.getRootForPath(resolvedPath);
4122
+ const relPath = this.rootManager.getRelativePathFromRoot(resolvedPath);
4123
+ const filesList = files.length > 0 ? files.join('\n') : '(no files)';
4124
+ const dirsList = dirs.length > 0 ? dirs.join('\n') : '(no directories)';
4125
+ return {
4126
+ content: [
4127
+ {
4128
+ type: 'text',
4129
+ text: `# Directory: ${targetPath}\n\n**Root**: ${root?.name}\n**Relative Path**: ${relPath || '/'}\n**Full Path**: \`${resolvedPath}\`\n\n## Directories (${dirs.length})\n\n${dirsList}\n\n## Files (${files.length})\n\n${filesList}`,
4130
+ },
4131
+ ],
4132
+ };
4133
+ }
4134
+ catch (error) {
4135
+ throw new McpAdrError(`Failed to read directory: ${error instanceof Error ? error.message : String(error)}`, 'DIRECTORY_READ_ERROR');
4136
+ }
4137
+ }
4138
+ async readFile(args) {
4139
+ const { filePath } = args;
4140
+ try {
4141
+ const fs = await import('fs/promises');
4142
+ const path = await import('path');
4143
+ // Resolve path (handle both relative and absolute paths)
4144
+ const safePath = path.resolve(filePath);
4145
+ // Security check: ensure path is within accessible roots
4146
+ if (!this.rootManager.isPathAllowed(safePath)) {
4147
+ const roots = this.rootManager.listRoots();
4148
+ const rootList = roots.map(r => ` - ${r.name}: ${r.path}`).join('\n');
4149
+ throw new McpAdrError(`Access denied: Path '${filePath}' is outside accessible roots.\n\nAccessible roots:\n${rootList}\n\nUse list_roots tool for more details.`, 'ACCESS_DENIED');
4150
+ }
4151
+ const content = await fs.readFile(safePath, 'utf-8');
4152
+ return {
4153
+ content: [
4154
+ {
4155
+ type: 'text',
4156
+ text: content,
4157
+ },
4158
+ ],
4159
+ };
4160
+ }
4161
+ catch (error) {
4162
+ throw new McpAdrError(`Failed to read file: ${error instanceof Error ? error.message : String(error)}`, 'FILE_READ_ERROR');
4163
+ }
4164
+ }
4165
+ async writeFile(args) {
4166
+ const { filePath, content } = args;
4167
+ try {
4168
+ const fs = await import('fs/promises');
4169
+ const path = await import('path');
4170
+ // Resolve path relative to project path for security
4171
+ const safePath = path.resolve(this.config.projectPath, filePath);
4172
+ // Security check: ensure path is within project directory
4173
+ if (!safePath.startsWith(this.config.projectPath)) {
4174
+ throw new McpAdrError('Access denied: Path is outside project directory', 'ACCESS_DENIED');
4175
+ }
4176
+ // Ensure directory exists
4177
+ await fs.mkdir(path.dirname(safePath), { recursive: true });
4178
+ // Write file
4179
+ await fs.writeFile(safePath, content, 'utf-8');
4180
+ return {
4181
+ content: [
4182
+ {
4183
+ type: 'text',
4184
+ text: `Successfully wrote to ${filePath}`,
4185
+ },
4186
+ ],
4187
+ };
4188
+ }
4189
+ catch (error) {
4190
+ throw new McpAdrError(`Failed to write file: ${error instanceof Error ? error.message : String(error)}`, 'FILE_WRITE_ERROR');
4191
+ }
4192
+ }
4193
+ async listDirectory(args) {
4194
+ const { path: dirPath } = args;
4195
+ try {
4196
+ const fs = await import('fs/promises');
4197
+ const path = await import('path');
4198
+ // Resolve path relative to project path for security
4199
+ const safePath = path.resolve(this.config.projectPath, dirPath);
4200
+ // Security check: ensure path is within project directory
4201
+ if (!safePath.startsWith(this.config.projectPath)) {
4202
+ throw new McpAdrError('Access denied: Path is outside project directory', 'ACCESS_DENIED');
4203
+ }
4204
+ const entries = await fs.readdir(safePath, { withFileTypes: true });
4205
+ const fileList = entries.map(entry => ({
4206
+ name: entry.name,
4207
+ type: entry.isDirectory() ? 'directory' : 'file',
4208
+ path: path.join(dirPath, entry.name),
4209
+ }));
4210
+ return {
4211
+ content: [
4212
+ {
4213
+ type: 'text',
4214
+ text: JSON.stringify(fileList, null, 2),
4215
+ },
4216
+ ],
4217
+ };
4218
+ }
4219
+ catch (error) {
4220
+ throw new McpAdrError(`Failed to list directory: ${error instanceof Error ? error.message : String(error)}`, 'DIRECTORY_LIST_ERROR');
4221
+ }
4222
+ }
4223
+ async generateDeploymentGuidance(args) {
4224
+ try {
4225
+ const { generateDeploymentGuidance } = await import('./tools/deployment-guidance-tool.js');
4226
+ return await generateDeploymentGuidance(args);
4227
+ }
4228
+ catch (error) {
4229
+ throw new McpAdrError(`Deployment guidance generation failed: ${error instanceof Error ? error.message : String(error)}`, 'DEPLOYMENT_GUIDANCE_ERROR');
4230
+ }
4231
+ }
4232
+ async smartGitPush(args) {
4233
+ try {
4234
+ const { smartGitPush } = await import('./tools/smart-git-push-tool-v2.js');
4235
+ return await smartGitPush(args);
4236
+ }
4237
+ catch (error) {
4238
+ throw new McpAdrError(`Smart git push failed: ${error instanceof Error ? error.message : String(error)}`, 'SMART_GIT_PUSH_ERROR');
4239
+ }
4240
+ }
4241
+ async deploymentReadiness(args) {
4242
+ try {
4243
+ const { deploymentReadiness } = await import('./tools/deployment-readiness-tool.js');
4244
+ return await deploymentReadiness(args);
4245
+ }
4246
+ catch (error) {
4247
+ throw new McpAdrError(`Deployment readiness check failed: ${error instanceof Error ? error.message : String(error)}`, 'DEPLOYMENT_READINESS_ERROR');
4248
+ }
4249
+ }
4250
+ async releaseTracking(args) {
4251
+ try {
4252
+ const { releaseTracking } = await import('./tools/release-tracking-tool.js');
4253
+ return await releaseTracking(args);
4254
+ }
4255
+ catch (error) {
4256
+ throw new McpAdrError(`Release tracking failed: ${error instanceof Error ? error.message : String(error)}`, 'RELEASE_TRACKING_ERROR');
4257
+ }
4258
+ }
4259
+ async generateAdrTodo(args) {
4260
+ try {
4261
+ const { generateAdrTodo } = await import('./tools/generate-adr-todo-tool.js');
4262
+ return await generateAdrTodo(args);
4263
+ }
4264
+ catch (error) {
4265
+ throw new McpAdrError(`generate_adr_todo failed: ${error instanceof Error ? error.message : String(error)}`, 'GENERATE_ADR_TODO_ERROR');
4266
+ }
4267
+ }
4268
+ async troubleshootGuidedWorkflow(args) {
4269
+ try {
4270
+ const { troubleshootGuidedWorkflow } = await import('./tools/troubleshoot-guided-workflow-tool.js');
4271
+ return await troubleshootGuidedWorkflow(args);
4272
+ }
4273
+ catch (error) {
4274
+ throw new McpAdrError(`Troubleshoot guided workflow failed: ${error instanceof Error ? error.message : String(error)}`, 'TROUBLESHOOT_GUIDED_WORKFLOW_ERROR');
4275
+ }
4276
+ }
4277
+ async smartScore(_args) {
4278
+ // Smart score tool was removed - return deprecation message
4279
+ return {
4280
+ content: [
4281
+ {
4282
+ type: 'text',
4283
+ text: `⚠️ **Smart Score Tool Deprecated**
4284
+
4285
+ This tool has been deprecated and replaced with memory-centric health scoring.
4286
+
4287
+ **Replacement:** The new MemoryHealthScoring system tracks:
4288
+ - Memory quality and relevance
4289
+ - Retrieval performance
4290
+ - Entity relationship coherence
4291
+ - Context utilization
4292
+ - Decision alignment
4293
+
4294
+ **Migration:** Health scoring is now integrated into the knowledge graph and automatically calculated based on memory usage patterns.`,
4295
+ },
4296
+ ],
4297
+ isError: false,
4298
+ };
4299
+ }
4300
+ async mcpPlanning(args) {
4301
+ try {
4302
+ const { mcpPlanning } = await import('./tools/mcp-planning-tool.js');
4303
+ return await mcpPlanning(args);
4304
+ }
4305
+ catch (error) {
4306
+ throw new McpAdrError(`MCP planning failed: ${error instanceof Error ? error.message : String(error)}`, 'MCP_PLANNING_ERROR');
4307
+ }
4308
+ }
4309
+ async memoryLoading(args) {
4310
+ try {
4311
+ const { MemoryLoadingTool } = await import('./tools/memory-loading-tool.js');
4312
+ const memoryTool = new MemoryLoadingTool();
4313
+ return await memoryTool.execute(args);
4314
+ }
4315
+ catch (error) {
4316
+ throw new McpAdrError(`Memory loading failed: ${error instanceof Error ? error.message : String(error)}`, 'MEMORY_LOADING_ERROR');
4317
+ }
4318
+ }
4319
+ async expandAnalysisSection(args) {
4320
+ try {
4321
+ const { expandAnalysisSection } = await import('./tools/expand-analysis-tool.js');
4322
+ return await expandAnalysisSection(args);
4323
+ }
4324
+ catch (error) {
4325
+ throw new McpAdrError(`Failed to expand analysis: ${error instanceof Error ? error.message : String(error)}`, 'EXPAND_ANALYSIS_ERROR');
4326
+ }
4327
+ }
4328
+ async interactiveAdrPlanning(args) {
4329
+ try {
4330
+ const { interactiveAdrPlanning } = await import('./tools/interactive-adr-planning-tool.js');
4331
+ return await interactiveAdrPlanning(args);
4332
+ }
4333
+ catch (error) {
4334
+ throw new McpAdrError(`Interactive ADR planning failed: ${error instanceof Error ? error.message : String(error)}`, 'INTERACTIVE_ADR_PLANNING_ERROR');
4335
+ }
4336
+ }
4337
+ /**
4338
+ * Tool chain orchestrator implementation
4339
+ */
4340
+ async toolChainOrchestrator(args) {
4341
+ try {
4342
+ const { toolChainOrchestrator } = await import('./tools/tool-chain-orchestrator.js');
4343
+ return await toolChainOrchestrator(args);
4344
+ }
4345
+ catch (error) {
4346
+ throw new McpAdrError(`Tool chain orchestration failed: ${error instanceof Error ? error.message : String(error)}`, 'TOOL_CHAIN_ORCHESTRATOR_ERROR');
4347
+ }
4348
+ }
4349
+ /**
4350
+ * Phase 3: Expand Memory Tool
4351
+ * Retrieves and expands stored content from tiered responses
4352
+ */
4353
+ async expandMemory(args) {
4354
+ try {
4355
+ const { expandMemory } = await import('./tools/conversation-memory-tool.js');
4356
+ return await expandMemory(args, this.conversationMemoryManager);
4357
+ }
4358
+ catch (error) {
4359
+ throw new McpAdrError(`Memory expansion failed: ${error instanceof Error ? error.message : String(error)}`, 'MEMORY_EXPANSION_ERROR');
4360
+ }
4361
+ }
4362
+ /**
4363
+ * Phase 3: Query Conversation History Tool
4364
+ * Searches and retrieves conversation sessions
4365
+ */
4366
+ async queryConversationHistory(args) {
4367
+ try {
4368
+ const { queryConversationHistory } = await import('./tools/conversation-memory-tool.js');
4369
+ return await queryConversationHistory(args, this.conversationMemoryManager);
4370
+ }
4371
+ catch (error) {
4372
+ throw new McpAdrError(`Conversation history query failed: ${error instanceof Error ? error.message : String(error)}`, 'CONVERSATION_QUERY_ERROR');
4373
+ }
4374
+ }
4375
+ /**
4376
+ * Phase 3: Get Conversation Snapshot Tool
4377
+ * Retrieves current conversation context
4378
+ */
4379
+ async getConversationSnapshot(args) {
4380
+ try {
4381
+ const { getConversationSnapshot } = await import('./tools/conversation-memory-tool.js');
4382
+ return await getConversationSnapshot(args, this.conversationMemoryManager);
4383
+ }
4384
+ catch (error) {
4385
+ throw new McpAdrError(`Conversation snapshot retrieval failed: ${error instanceof Error ? error.message : String(error)}`, 'SNAPSHOT_ERROR');
4386
+ }
4387
+ }
4388
+ /**
4389
+ * Phase 3: Get Memory Statistics Tool
4390
+ * Retrieves conversation memory statistics
4391
+ */
4392
+ async getMemoryStats() {
4393
+ try {
4394
+ const { getMemoryStats } = await import('./tools/conversation-memory-tool.js');
4395
+ return await getMemoryStats(this.conversationMemoryManager);
4396
+ }
4397
+ catch (error) {
4398
+ throw new McpAdrError(`Memory stats retrieval failed: ${error instanceof Error ? error.message : String(error)}`, 'MEMORY_STATS_ERROR');
4399
+ }
4400
+ }
4401
+ /**
4402
+ * Update Knowledge Tool (ADR-018)
4403
+ * Simple CRUD operations for knowledge graph
4404
+ */
4405
+ async updateKnowledge(args) {
4406
+ try {
4407
+ const { updateKnowledge } = await import('./tools/update-knowledge-tool.js');
4408
+ return await updateKnowledge(args, createNoOpContext(), this.kgManager);
4409
+ }
4410
+ catch (error) {
4411
+ throw new McpAdrError(`Knowledge update failed: ${error instanceof Error ? error.message : String(error)}`, 'KNOWLEDGE_UPDATE_ERROR');
4412
+ }
4413
+ }
4414
+ /**
4415
+ * Get Server Context Tool
4416
+ * Generates comprehensive server context file for LLM @ referencing
4417
+ */
4418
+ async getServerContext(args) {
4419
+ try {
4420
+ const { getServerContext } = await import('./tools/get-server-context-tool.js');
4421
+ return await getServerContext(args, this.kgManager, this.memoryEntityManager, this.conversationMemoryManager);
4422
+ }
4423
+ catch (error) {
4424
+ throw new McpAdrError(`Server context generation failed: ${error instanceof Error ? error.message : String(error)}`, 'SERVER_CONTEXT_ERROR');
4425
+ }
4426
+ }
4427
+ /**
4428
+ * Get Current Datetime Tool
4429
+ * Returns the current date and time in various formats for ADR generation and timestamping
4430
+ */
4431
+ async getCurrentDatetime(args) {
4432
+ const { timezone = 'UTC', format = 'all', includeTimestamp = true } = args;
4433
+ try {
4434
+ const now = new Date();
4435
+ // Format date for different timezones
4436
+ const formatOptions = {
4437
+ timeZone: timezone,
4438
+ year: 'numeric',
4439
+ month: '2-digit',
4440
+ day: '2-digit',
4441
+ hour: '2-digit',
4442
+ minute: '2-digit',
4443
+ second: '2-digit',
4444
+ hour12: false,
4445
+ };
4446
+ // Get date parts for the specified timezone
4447
+ const formatter = new Intl.DateTimeFormat('en-CA', {
4448
+ timeZone: timezone,
4449
+ year: 'numeric',
4450
+ month: '2-digit',
4451
+ day: '2-digit',
4452
+ });
4453
+ const parts = formatter.formatToParts(now);
4454
+ const year = parts.find(p => p.type === 'year')?.value || '';
4455
+ const month = parts.find(p => p.type === 'month')?.value || '';
4456
+ const day = parts.find(p => p.type === 'day')?.value || '';
4457
+ // ADR date format: YYYY-MM-DD
4458
+ const adrDate = `${year}-${month}-${day}`;
4459
+ // ISO 8601 format
4460
+ const isoDate = now.toISOString();
4461
+ // Human-readable format
4462
+ const humanFormatter = new Intl.DateTimeFormat('en-US', {
4463
+ ...formatOptions,
4464
+ weekday: 'long',
4465
+ month: 'long',
4466
+ });
4467
+ const humanDate = humanFormatter.format(now);
4468
+ // Build response based on requested format
4469
+ let responseData = {};
4470
+ switch (format) {
4471
+ case 'iso':
4472
+ responseData = { iso: isoDate };
4473
+ break;
4474
+ case 'human':
4475
+ responseData = { human: humanDate };
4476
+ break;
4477
+ case 'adr':
4478
+ responseData = { adr: adrDate };
4479
+ break;
4480
+ case 'all':
4481
+ default:
4482
+ responseData = {
4483
+ iso: isoDate,
4484
+ human: humanDate,
4485
+ adr: adrDate,
4486
+ timezone: timezone,
4487
+ };
4488
+ }
4489
+ if (includeTimestamp) {
4490
+ responseData['timestamp'] = now.getTime();
4491
+ }
4492
+ const responseText = `# Current Date and Time
4493
+
4494
+ ## Formats
4495
+ ${format === 'all' || format === 'iso' ? `- **ISO 8601**: ${isoDate}` : ''}
4496
+ ${format === 'all' || format === 'human' ? `- **Human Readable**: ${humanDate}` : ''}
4497
+ ${format === 'all' || format === 'adr' ? `- **ADR Date (YYYY-MM-DD)**: ${adrDate}` : ''}
4498
+ ${format === 'all' ? `- **Timezone**: ${timezone}` : ''}
4499
+ ${includeTimestamp ? `- **Unix Timestamp (ms)**: ${now.getTime()}` : ''}
4500
+
4501
+ ## Usage for ADR Generation
4502
+
4503
+ When generating ADRs, use the ADR date format (\`${adrDate}\`) in the Date field:
4504
+
4505
+ \`\`\`markdown
4506
+ # ADR-XXXX: [Title]
4507
+
4508
+ ## Date
4509
+ ${adrDate}
4510
+
4511
+ ## Status
4512
+ Proposed
4513
+ \`\`\`
4514
+
4515
+ ## Raw Data
4516
+
4517
+ \`\`\`json
4518
+ ${JSON.stringify(responseData, null, 2)}
4519
+ \`\`\`
4520
+ `;
4521
+ return {
4522
+ content: [
4523
+ {
4524
+ type: 'text',
4525
+ text: responseText,
4526
+ },
4527
+ ],
4528
+ };
4529
+ }
4530
+ catch (error) {
4531
+ throw new McpAdrError(`Failed to get current datetime: ${error instanceof Error ? error.message : String(error)}`, 'DATETIME_ERROR');
4532
+ }
4533
+ }
4534
+ /**
4535
+ * Set Project Path Tool - Dynamic Session Configuration
4536
+ *
4537
+ * @description Dynamically sets the active project path for the current session.
4538
+ * This allows switching between projects without restarting the server or modifying
4539
+ * environment variables. Updates both the config and the RootManager.
4540
+ *
4541
+ * @param args - Set project path arguments
4542
+ * @param args.path - Absolute path to the project directory
4543
+ * @param args.validatePath - Whether to validate the path exists (default: true)
4544
+ * @returns Promise<CallToolResult> - Confirmation of the path change
4545
+ */
4546
+ async setProjectPath(args) {
4547
+ const { path: newPath, validatePath = true } = args;
4548
+ const { resolve } = await import('path');
4549
+ try {
4550
+ // Resolve to absolute path
4551
+ const absolutePath = resolve(newPath);
4552
+ const previousPath = this.config.projectPath;
4553
+ // Validate the path if requested
4554
+ if (validatePath) {
4555
+ await validateProjectPath(absolutePath);
4556
+ }
4557
+ // Update the server configuration
4558
+ this.config.projectPath = absolutePath;
4559
+ // Re-initialize the RootManager with the new path
4560
+ this.rootManager = new RootManager(absolutePath, this.config.adrDirectory);
4561
+ this.logger.info(`Project path changed: ${previousPath} -> ${absolutePath}`);
4562
+ const responseText = `# Project Path Updated
4563
+
4564
+ ## Configuration
4565
+ - **Previous Path**: \`${previousPath}\`
4566
+ - **New Path**: \`${absolutePath}\`
4567
+ - **ADR Directory**: \`${this.config.adrDirectory}\`
4568
+ - **Full ADR Path**: \`${resolve(absolutePath, this.config.adrDirectory)}\`
4569
+
4570
+ ## Status
4571
+ ✅ Project path successfully updated for this session.
4572
+
4573
+ ## Note
4574
+ All subsequent tool calls will use this path as the default project path.
4575
+ You can still override it per-tool by passing \`projectPath\` as an argument.
4576
+
4577
+ To make this permanent, set the \`PROJECT_PATH\` environment variable.
4578
+ `;
4579
+ return {
4580
+ content: [
4581
+ {
4582
+ type: 'text',
4583
+ text: responseText,
4584
+ },
4585
+ ],
4586
+ };
4587
+ }
4588
+ catch (error) {
4589
+ throw new McpAdrError(`Failed to set project path: ${error instanceof Error ? error.message : String(error)}`, 'SET_PROJECT_PATH_ERROR');
4590
+ }
4591
+ }
4592
+ /**
4593
+ * Load Prompt Tool - CE-MCP Phase 4 Lazy Loading
4594
+ *
4595
+ * @description Loads prompts on-demand instead of eagerly loading all prompts at startup.
4596
+ * This reduces token usage by ~96% (from 28K tokens to ~1K on-demand).
4597
+ *
4598
+ * @param args - Load prompt arguments
4599
+ * @param args.promptName - Name of the prompt to load
4600
+ * @param args.section - Optional section within the prompt
4601
+ * @param args.estimateOnly - If true, returns only token estimate
4602
+ * @returns Promise<CallToolResult> - Loaded prompt content or estimate
4603
+ */
4604
+ async loadPrompt(args) {
4605
+ const { promptName, section, estimateOnly = false } = args;
4606
+ // Import the prompt catalog dynamically to enable lazy loading
4607
+ const { getPromptLoader, getPromptMetadata, calculateTokenSavings } = await import('./prompts/prompt-catalog.js');
4608
+ const metadata = getPromptMetadata(promptName);
4609
+ if (!metadata) {
4610
+ const availablePrompts = [
4611
+ 'adr-suggestion',
4612
+ 'deployment-analysis',
4613
+ 'environment-analysis',
4614
+ 'research-question',
4615
+ 'rule-generation',
4616
+ 'analysis',
4617
+ 'research-integration',
4618
+ 'validated-pattern',
4619
+ 'security',
4620
+ ];
4621
+ return {
4622
+ content: [
4623
+ {
4624
+ type: 'text',
4625
+ text: JSON.stringify({
4626
+ success: false,
4627
+ error: `Unknown prompt: ${promptName}`,
4628
+ availablePrompts,
4629
+ hint: 'Use one of the available prompt names listed above',
4630
+ }, null, 2),
4631
+ },
4632
+ ],
4633
+ isError: true,
4634
+ };
4635
+ }
4636
+ // If estimate only, return token information without loading
4637
+ if (estimateOnly) {
4638
+ const loader = getPromptLoader();
4639
+ const estimatedTokens = loader.getEstimatedTokens(promptName, section);
4640
+ const savings = calculateTokenSavings([promptName]);
4641
+ return {
4642
+ content: [
4643
+ {
4644
+ type: 'text',
4645
+ text: JSON.stringify({
4646
+ success: true,
4647
+ promptName,
4648
+ section: section || 'full',
4649
+ estimatedTokens,
4650
+ metadata: {
4651
+ file: metadata.file,
4652
+ category: metadata.category,
4653
+ totalTokens: metadata.tokens,
4654
+ availableSections: metadata.sections,
4655
+ loadOnDemand: metadata.loadOnDemand,
4656
+ },
4657
+ tokenSavings: {
4658
+ loaded: savings.loaded,
4659
+ total: savings.total,
4660
+ saved: savings.saved,
4661
+ percentage: `${savings.percentage}%`,
4662
+ },
4663
+ }, null, 2),
4664
+ },
4665
+ ],
4666
+ };
4667
+ }
4668
+ // Load the prompt content
4669
+ try {
4670
+ const loader = getPromptLoader();
4671
+ const content = await loader.loadPrompt(promptName, section);
4672
+ return {
4673
+ content: [
4674
+ {
4675
+ type: 'text',
4676
+ text: `# Loaded Prompt: ${promptName}${section ? ` (section: ${section})` : ''}
4677
+
4678
+ ## Metadata
4679
+ - **Category**: ${metadata.category}
4680
+ - **Estimated Tokens**: ${metadata.tokens}
4681
+ - **Available Sections**: ${metadata.sections.join(', ')}
4682
+
4683
+ ## Content
4684
+
4685
+ ${content}
4686
+
4687
+ ---
4688
+
4689
+ *Loaded on-demand via CE-MCP lazy loading system. Token savings: ~96% compared to eager loading all prompts.*
4690
+ `,
4691
+ },
4692
+ ],
4693
+ };
4694
+ }
4695
+ catch (error) {
4696
+ throw new McpAdrError(`Failed to load prompt '${promptName}'${section ? ` section '${section}'` : ''}: ${error instanceof Error ? error.message : String(error)}`, 'PROMPT_LOAD_ERROR');
4697
+ }
4698
+ }
4699
+ }
4700
+ //# sourceMappingURL=mcp-adr-analysis-server.js.map