mcp-adr-analysis-server 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (131) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +608 -0
  3. package/dist/src/index.d.ts +10 -0
  4. package/dist/src/index.d.ts.map +1 -0
  5. package/dist/src/index.js +1722 -0
  6. package/dist/src/index.js.map +1 -0
  7. package/dist/src/prompts/adr-suggestion-prompts.d.ts +24 -0
  8. package/dist/src/prompts/adr-suggestion-prompts.d.ts.map +1 -0
  9. package/dist/src/prompts/adr-suggestion-prompts.js +383 -0
  10. package/dist/src/prompts/adr-suggestion-prompts.js.map +1 -0
  11. package/dist/src/prompts/analysis-prompts.d.ts +24 -0
  12. package/dist/src/prompts/analysis-prompts.d.ts.map +1 -0
  13. package/dist/src/prompts/analysis-prompts.js +489 -0
  14. package/dist/src/prompts/analysis-prompts.js.map +1 -0
  15. package/dist/src/prompts/deployment-analysis-prompts.d.ts +54 -0
  16. package/dist/src/prompts/deployment-analysis-prompts.d.ts.map +1 -0
  17. package/dist/src/prompts/deployment-analysis-prompts.js +712 -0
  18. package/dist/src/prompts/deployment-analysis-prompts.js.map +1 -0
  19. package/dist/src/prompts/environment-analysis-prompts.d.ts +34 -0
  20. package/dist/src/prompts/environment-analysis-prompts.d.ts.map +1 -0
  21. package/dist/src/prompts/environment-analysis-prompts.js +724 -0
  22. package/dist/src/prompts/environment-analysis-prompts.js.map +1 -0
  23. package/dist/src/prompts/index.d.ts +43 -0
  24. package/dist/src/prompts/index.d.ts.map +1 -0
  25. package/dist/src/prompts/index.js +384 -0
  26. package/dist/src/prompts/index.js.map +1 -0
  27. package/dist/src/prompts/research-integration-prompts.d.ts +43 -0
  28. package/dist/src/prompts/research-integration-prompts.d.ts.map +1 -0
  29. package/dist/src/prompts/research-integration-prompts.js +398 -0
  30. package/dist/src/prompts/research-integration-prompts.js.map +1 -0
  31. package/dist/src/prompts/research-question-prompts.d.ts +75 -0
  32. package/dist/src/prompts/research-question-prompts.d.ts.map +1 -0
  33. package/dist/src/prompts/research-question-prompts.js +695 -0
  34. package/dist/src/prompts/research-question-prompts.js.map +1 -0
  35. package/dist/src/prompts/rule-generation-prompts.d.ts +63 -0
  36. package/dist/src/prompts/rule-generation-prompts.d.ts.map +1 -0
  37. package/dist/src/prompts/rule-generation-prompts.js +630 -0
  38. package/dist/src/prompts/rule-generation-prompts.js.map +1 -0
  39. package/dist/src/prompts/security-prompts.d.ts +23 -0
  40. package/dist/src/prompts/security-prompts.d.ts.map +1 -0
  41. package/dist/src/prompts/security-prompts.js +287 -0
  42. package/dist/src/prompts/security-prompts.js.map +1 -0
  43. package/dist/src/resources/index.d.ts +24 -0
  44. package/dist/src/resources/index.d.ts.map +1 -0
  45. package/dist/src/resources/index.js +458 -0
  46. package/dist/src/resources/index.js.map +1 -0
  47. package/dist/src/tools/adr-suggestion-tool.d.ts +40 -0
  48. package/dist/src/tools/adr-suggestion-tool.d.ts.map +1 -0
  49. package/dist/src/tools/adr-suggestion-tool.js +338 -0
  50. package/dist/src/tools/adr-suggestion-tool.js.map +1 -0
  51. package/dist/src/tools/content-masking-tool.d.ts +52 -0
  52. package/dist/src/tools/content-masking-tool.d.ts.map +1 -0
  53. package/dist/src/tools/content-masking-tool.js +206 -0
  54. package/dist/src/tools/content-masking-tool.js.map +1 -0
  55. package/dist/src/tools/deployment-analysis-tool.d.ts +39 -0
  56. package/dist/src/tools/deployment-analysis-tool.d.ts.map +1 -0
  57. package/dist/src/tools/deployment-analysis-tool.js +310 -0
  58. package/dist/src/tools/deployment-analysis-tool.js.map +1 -0
  59. package/dist/src/tools/environment-analysis-tool.d.ts +16 -0
  60. package/dist/src/tools/environment-analysis-tool.d.ts.map +1 -0
  61. package/dist/src/tools/environment-analysis-tool.js +298 -0
  62. package/dist/src/tools/environment-analysis-tool.js.map +1 -0
  63. package/dist/src/tools/research-integration-tool.d.ts +44 -0
  64. package/dist/src/tools/research-integration-tool.d.ts.map +1 -0
  65. package/dist/src/tools/research-integration-tool.js +429 -0
  66. package/dist/src/tools/research-integration-tool.js.map +1 -0
  67. package/dist/src/tools/research-question-tool.d.ts +55 -0
  68. package/dist/src/tools/research-question-tool.d.ts.map +1 -0
  69. package/dist/src/tools/research-question-tool.js +333 -0
  70. package/dist/src/tools/research-question-tool.js.map +1 -0
  71. package/dist/src/tools/rule-generation-tool.d.ts +49 -0
  72. package/dist/src/tools/rule-generation-tool.d.ts.map +1 -0
  73. package/dist/src/tools/rule-generation-tool.js +432 -0
  74. package/dist/src/tools/rule-generation-tool.js.map +1 -0
  75. package/dist/src/types/index.d.ts +531 -0
  76. package/dist/src/types/index.d.ts.map +1 -0
  77. package/dist/src/types/index.js +129 -0
  78. package/dist/src/types/index.js.map +1 -0
  79. package/dist/src/utils/adr-suggestions.d.ts +104 -0
  80. package/dist/src/utils/adr-suggestions.d.ts.map +1 -0
  81. package/dist/src/utils/adr-suggestions.js +228 -0
  82. package/dist/src/utils/adr-suggestions.js.map +1 -0
  83. package/dist/src/utils/cache.d.ts +51 -0
  84. package/dist/src/utils/cache.d.ts.map +1 -0
  85. package/dist/src/utils/cache.js +243 -0
  86. package/dist/src/utils/cache.js.map +1 -0
  87. package/dist/src/utils/config.d.ts +65 -0
  88. package/dist/src/utils/config.d.ts.map +1 -0
  89. package/dist/src/utils/config.js +118 -0
  90. package/dist/src/utils/config.js.map +1 -0
  91. package/dist/src/utils/content-masking.d.ts +79 -0
  92. package/dist/src/utils/content-masking.d.ts.map +1 -0
  93. package/dist/src/utils/content-masking.js +203 -0
  94. package/dist/src/utils/content-masking.js.map +1 -0
  95. package/dist/src/utils/deployment-analysis.d.ts +67 -0
  96. package/dist/src/utils/deployment-analysis.d.ts.map +1 -0
  97. package/dist/src/utils/deployment-analysis.js +263 -0
  98. package/dist/src/utils/deployment-analysis.js.map +1 -0
  99. package/dist/src/utils/environment-analysis.d.ts +76 -0
  100. package/dist/src/utils/environment-analysis.d.ts.map +1 -0
  101. package/dist/src/utils/environment-analysis.js +329 -0
  102. package/dist/src/utils/environment-analysis.js.map +1 -0
  103. package/dist/src/utils/file-system.d.ts +63 -0
  104. package/dist/src/utils/file-system.d.ts.map +1 -0
  105. package/dist/src/utils/file-system.js +189 -0
  106. package/dist/src/utils/file-system.js.map +1 -0
  107. package/dist/src/utils/output-masking.d.ts +45 -0
  108. package/dist/src/utils/output-masking.d.ts.map +1 -0
  109. package/dist/src/utils/output-masking.js +200 -0
  110. package/dist/src/utils/output-masking.js.map +1 -0
  111. package/dist/src/utils/research-documentation.d.ts +58 -0
  112. package/dist/src/utils/research-documentation.d.ts.map +1 -0
  113. package/dist/src/utils/research-documentation.js +438 -0
  114. package/dist/src/utils/research-documentation.js.map +1 -0
  115. package/dist/src/utils/research-integration.d.ts +89 -0
  116. package/dist/src/utils/research-integration.d.ts.map +1 -0
  117. package/dist/src/utils/research-integration.js +432 -0
  118. package/dist/src/utils/research-integration.js.map +1 -0
  119. package/dist/src/utils/research-questions.d.ts +97 -0
  120. package/dist/src/utils/research-questions.d.ts.map +1 -0
  121. package/dist/src/utils/research-questions.js +319 -0
  122. package/dist/src/utils/research-questions.js.map +1 -0
  123. package/dist/src/utils/rule-format.d.ts +76 -0
  124. package/dist/src/utils/rule-format.d.ts.map +1 -0
  125. package/dist/src/utils/rule-format.js +257 -0
  126. package/dist/src/utils/rule-format.js.map +1 -0
  127. package/dist/src/utils/rule-generation.d.ts +86 -0
  128. package/dist/src/utils/rule-generation.d.ts.map +1 -0
  129. package/dist/src/utils/rule-generation.js +330 -0
  130. package/dist/src/utils/rule-generation.js.map +1 -0
  131. package/package.json +71 -0
@@ -0,0 +1,1722 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * MCP ADR Analysis Server
4
+ * Main entry point for the Model Context Protocol server
5
+ *
6
+ * This server provides Tools, Resources, and Prompts for analyzing
7
+ * Architectural Decision Records and project architecture.
8
+ */
9
+ import { Server } from '@modelcontextprotocol/sdk/server/index.js';
10
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
11
+ import { CallToolRequestSchema, ListToolsRequestSchema, ListResourcesRequestSchema, ReadResourceRequestSchema, ListPromptsRequestSchema, GetPromptRequestSchema } from '@modelcontextprotocol/sdk/types.js';
12
+ import { McpAdrError } from './types/index.js';
13
+ import { maskMcpResponse, createMaskingConfig } from './utils/output-masking.js';
14
+ import { loadConfig, validateProjectPath, createLogger, printConfigSummary } from './utils/config.js';
15
+ /**
16
+ * Server configuration
17
+ */
18
+ const SERVER_INFO = {
19
+ name: 'mcp-adr-analysis-server',
20
+ version: '1.0.0',
21
+ description: 'MCP server for analyzing Architectural Decision Records and project architecture'
22
+ };
23
+ /**
24
+ * Main server class
25
+ */
26
+ class McpAdrAnalysisServer {
27
+ server;
28
+ maskingConfig;
29
+ config;
30
+ logger;
31
+ constructor() {
32
+ // Load and validate configuration
33
+ this.config = loadConfig();
34
+ this.logger = createLogger(this.config);
35
+ // Print configuration summary
36
+ printConfigSummary(this.config);
37
+ // Note: Validation will be done during startup
38
+ this.server = new Server(SERVER_INFO, {
39
+ capabilities: {
40
+ tools: {},
41
+ resources: {},
42
+ prompts: {}
43
+ }
44
+ });
45
+ this.maskingConfig = createMaskingConfig();
46
+ this.setupHandlers();
47
+ }
48
+ /**
49
+ * Validate configuration and project setup
50
+ */
51
+ async validateConfiguration() {
52
+ try {
53
+ await validateProjectPath(this.config.projectPath);
54
+ this.logger.info(`Project path validated: ${this.config.projectPath}`);
55
+ }
56
+ catch (error) {
57
+ this.logger.error(`Configuration validation failed: ${error.message}`);
58
+ throw error;
59
+ }
60
+ }
61
+ /**
62
+ * Public health check method for testing
63
+ */
64
+ async healthCheck() {
65
+ await this.validateConfiguration();
66
+ this.logger.info('Health check completed successfully');
67
+ }
68
+ /**
69
+ * Setup MCP protocol handlers
70
+ */
71
+ setupHandlers() {
72
+ // Tools handler
73
+ this.server.setRequestHandler(ListToolsRequestSchema, async () => {
74
+ return {
75
+ tools: [
76
+ {
77
+ name: 'analyze_project_ecosystem',
78
+ description: 'Analyze the project ecosystem including technology stack, patterns, and architecture',
79
+ inputSchema: {
80
+ type: 'object',
81
+ properties: {
82
+ projectPath: {
83
+ type: 'string',
84
+ description: 'Path to the project directory to analyze (optional, uses configured PROJECT_PATH if not provided)'
85
+ },
86
+ includePatterns: {
87
+ type: 'array',
88
+ items: { type: 'string' },
89
+ description: 'File patterns to include in analysis'
90
+ }
91
+ },
92
+ required: []
93
+ }
94
+ },
95
+ {
96
+ name: 'get_architectural_context',
97
+ description: 'Get detailed architectural context for specific files or the entire project',
98
+ inputSchema: {
99
+ type: 'object',
100
+ properties: {
101
+ filePath: {
102
+ type: 'string',
103
+ description: 'Specific file path to analyze (optional, analyzes entire project if not provided)'
104
+ },
105
+ includeCompliance: {
106
+ type: 'boolean',
107
+ description: 'Include compliance checks in the analysis',
108
+ default: true
109
+ }
110
+ }
111
+ }
112
+ },
113
+ {
114
+ name: 'generate_adrs_from_prd',
115
+ description: 'Generate Architectural Decision Records from a Product Requirements Document',
116
+ inputSchema: {
117
+ type: 'object',
118
+ properties: {
119
+ prdPath: {
120
+ type: 'string',
121
+ description: 'Path to the PRD.md file'
122
+ },
123
+ outputDirectory: {
124
+ type: 'string',
125
+ description: 'Directory to output generated ADRs (optional, uses configured ADR_DIRECTORY if not provided)'
126
+ }
127
+ },
128
+ required: ['prdPath']
129
+ }
130
+ },
131
+ {
132
+ name: 'generate_adr_todo',
133
+ description: 'Generate or update todo.md from existing ADRs',
134
+ inputSchema: {
135
+ type: 'object',
136
+ properties: {
137
+ adrDirectory: {
138
+ type: 'string',
139
+ description: 'Directory containing ADR files (optional, uses configured ADR_DIRECTORY if not provided)'
140
+ },
141
+ scope: {
142
+ type: 'string',
143
+ enum: ['all', 'pending', 'in_progress'],
144
+ description: 'Scope of tasks to include',
145
+ default: 'all'
146
+ }
147
+ }
148
+ }
149
+ },
150
+ {
151
+ name: 'analyze_content_security',
152
+ description: 'Analyze content for sensitive information using AI-powered detection',
153
+ inputSchema: {
154
+ type: 'object',
155
+ properties: {
156
+ content: {
157
+ type: 'string',
158
+ description: 'Content to analyze for sensitive information'
159
+ },
160
+ contentType: {
161
+ type: 'string',
162
+ enum: ['code', 'documentation', 'configuration', 'logs', 'general'],
163
+ description: 'Type of content being analyzed',
164
+ default: 'general'
165
+ },
166
+ userDefinedPatterns: {
167
+ type: 'array',
168
+ items: { type: 'string' },
169
+ description: 'User-defined sensitive patterns to detect'
170
+ }
171
+ },
172
+ required: ['content']
173
+ }
174
+ },
175
+ {
176
+ name: 'generate_content_masking',
177
+ description: 'Generate masking instructions for detected sensitive content',
178
+ inputSchema: {
179
+ type: 'object',
180
+ properties: {
181
+ content: {
182
+ type: 'string',
183
+ description: 'Content to mask'
184
+ },
185
+ detectedItems: {
186
+ type: 'array',
187
+ items: {
188
+ type: 'object',
189
+ properties: {
190
+ type: { type: 'string' },
191
+ content: { type: 'string' },
192
+ startPosition: { type: 'number' },
193
+ endPosition: { type: 'number' },
194
+ severity: { type: 'string' }
195
+ }
196
+ },
197
+ description: 'Detected sensitive items to mask'
198
+ },
199
+ maskingStrategy: {
200
+ type: 'string',
201
+ enum: ['full', 'partial', 'placeholder', 'environment'],
202
+ description: 'Strategy for masking content',
203
+ default: 'full'
204
+ }
205
+ },
206
+ required: ['content', 'detectedItems']
207
+ }
208
+ },
209
+ {
210
+ name: 'configure_custom_patterns',
211
+ description: 'Configure custom sensitive patterns for a project',
212
+ inputSchema: {
213
+ type: 'object',
214
+ properties: {
215
+ projectPath: {
216
+ type: 'string',
217
+ description: 'Path to the project directory'
218
+ },
219
+ existingPatterns: {
220
+ type: 'array',
221
+ items: { type: 'string' },
222
+ description: 'Existing patterns to consider'
223
+ }
224
+ },
225
+ required: ['projectPath']
226
+ }
227
+ },
228
+ {
229
+ name: 'apply_basic_content_masking',
230
+ description: 'Apply basic content masking (fallback when AI is not available)',
231
+ inputSchema: {
232
+ type: 'object',
233
+ properties: {
234
+ content: {
235
+ type: 'string',
236
+ description: 'Content to mask'
237
+ },
238
+ maskingStrategy: {
239
+ type: 'string',
240
+ enum: ['full', 'partial', 'placeholder'],
241
+ description: 'Strategy for masking content',
242
+ default: 'full'
243
+ }
244
+ },
245
+ required: ['content']
246
+ }
247
+ },
248
+ {
249
+ name: 'validate_content_masking',
250
+ description: 'Validate that content masking was applied correctly',
251
+ inputSchema: {
252
+ type: 'object',
253
+ properties: {
254
+ originalContent: {
255
+ type: 'string',
256
+ description: 'Original content before masking'
257
+ },
258
+ maskedContent: {
259
+ type: 'string',
260
+ description: 'Content after masking'
261
+ }
262
+ },
263
+ required: ['originalContent', 'maskedContent']
264
+ }
265
+ },
266
+ {
267
+ name: 'manage_cache',
268
+ description: 'Manage MCP resource cache (clear, stats, cleanup)',
269
+ inputSchema: {
270
+ type: 'object',
271
+ properties: {
272
+ action: {
273
+ type: 'string',
274
+ enum: ['clear', 'stats', 'cleanup', 'invalidate'],
275
+ description: 'Cache management action to perform'
276
+ },
277
+ key: {
278
+ type: 'string',
279
+ description: 'Specific cache key to invalidate (for invalidate action)'
280
+ }
281
+ },
282
+ required: ['action']
283
+ }
284
+ },
285
+ {
286
+ name: 'configure_output_masking',
287
+ description: 'Configure content masking for all MCP outputs',
288
+ inputSchema: {
289
+ type: 'object',
290
+ properties: {
291
+ enabled: {
292
+ type: 'boolean',
293
+ description: 'Enable or disable output masking'
294
+ },
295
+ strategy: {
296
+ type: 'string',
297
+ enum: ['full', 'partial', 'placeholder', 'environment'],
298
+ description: 'Masking strategy to use'
299
+ },
300
+ customPatterns: {
301
+ type: 'array',
302
+ items: { type: 'string' },
303
+ description: 'Custom patterns to mask'
304
+ },
305
+ action: {
306
+ type: 'string',
307
+ enum: ['get', 'set', 'reset'],
308
+ description: 'Configuration action',
309
+ default: 'get'
310
+ }
311
+ }
312
+ }
313
+ },
314
+ {
315
+ name: 'suggest_adrs',
316
+ description: 'Suggest ADRs based on project analysis and implicit decisions',
317
+ inputSchema: {
318
+ type: 'object',
319
+ properties: {
320
+ projectPath: {
321
+ type: 'string',
322
+ description: 'Path to the project directory',
323
+ default: '.'
324
+ },
325
+ analysisType: {
326
+ type: 'string',
327
+ enum: ['implicit_decisions', 'code_changes', 'comprehensive'],
328
+ description: 'Type of analysis to perform',
329
+ default: 'comprehensive'
330
+ },
331
+ beforeCode: {
332
+ type: 'string',
333
+ description: 'Code before changes (for code_changes analysis)'
334
+ },
335
+ afterCode: {
336
+ type: 'string',
337
+ description: 'Code after changes (for code_changes analysis)'
338
+ },
339
+ changeDescription: {
340
+ type: 'string',
341
+ description: 'Description of the changes (for code_changes analysis)'
342
+ },
343
+ commitMessages: {
344
+ type: 'array',
345
+ items: { type: 'string' },
346
+ description: 'Related commit messages (for code_changes analysis)'
347
+ },
348
+ existingAdrs: {
349
+ type: 'array',
350
+ items: { type: 'string' },
351
+ description: 'List of existing ADR titles to avoid duplication'
352
+ }
353
+ }
354
+ }
355
+ },
356
+ {
357
+ name: 'generate_adr_from_decision',
358
+ description: 'Generate a complete ADR from decision data',
359
+ inputSchema: {
360
+ type: 'object',
361
+ properties: {
362
+ decisionData: {
363
+ type: 'object',
364
+ properties: {
365
+ title: { type: 'string', description: 'Decision title' },
366
+ context: { type: 'string', description: 'Decision context and problem' },
367
+ decision: { type: 'string', description: 'The architectural decision' },
368
+ consequences: { type: 'string', description: 'Decision consequences' },
369
+ alternatives: {
370
+ type: 'array',
371
+ items: { type: 'string' },
372
+ description: 'Alternative approaches considered'
373
+ },
374
+ evidence: {
375
+ type: 'array',
376
+ items: { type: 'string' },
377
+ description: 'Supporting evidence for the decision'
378
+ }
379
+ },
380
+ required: ['title', 'context', 'decision', 'consequences']
381
+ },
382
+ templateFormat: {
383
+ type: 'string',
384
+ enum: ['nygard', 'madr', 'custom'],
385
+ description: 'ADR template format to use',
386
+ default: 'nygard'
387
+ },
388
+ existingAdrs: {
389
+ type: 'array',
390
+ items: { type: 'string' },
391
+ description: 'List of existing ADRs for numbering and references'
392
+ },
393
+ adrDirectory: {
394
+ type: 'string',
395
+ description: 'Directory where ADRs are stored',
396
+ default: 'docs/adrs'
397
+ }
398
+ },
399
+ required: ['decisionData']
400
+ }
401
+ },
402
+ {
403
+ name: 'discover_existing_adrs',
404
+ description: 'Discover and catalog existing ADRs in the project',
405
+ inputSchema: {
406
+ type: 'object',
407
+ properties: {
408
+ adrDirectory: {
409
+ type: 'string',
410
+ description: 'Directory to search for ADRs',
411
+ default: 'docs/adrs'
412
+ },
413
+ includeContent: {
414
+ type: 'boolean',
415
+ description: 'Whether to include ADR content in analysis',
416
+ default: false
417
+ }
418
+ }
419
+ }
420
+ },
421
+ {
422
+ name: 'incorporate_research',
423
+ description: 'Incorporate research findings into architectural decisions',
424
+ inputSchema: {
425
+ type: 'object',
426
+ properties: {
427
+ researchPath: {
428
+ type: 'string',
429
+ description: 'Path to research directory',
430
+ default: 'docs/research'
431
+ },
432
+ adrDirectory: {
433
+ type: 'string',
434
+ description: 'Path to ADR directory',
435
+ default: 'docs/adrs'
436
+ },
437
+ analysisType: {
438
+ type: 'string',
439
+ enum: ['monitor', 'extract_topics', 'evaluate_impact', 'generate_updates', 'comprehensive'],
440
+ description: 'Type of research analysis to perform',
441
+ default: 'comprehensive'
442
+ },
443
+ existingTopics: {
444
+ type: 'array',
445
+ items: { type: 'string' },
446
+ description: 'Previously identified research topics'
447
+ },
448
+ researchTopics: {
449
+ type: 'array',
450
+ items: {
451
+ type: 'object',
452
+ properties: {
453
+ id: { type: 'string' },
454
+ title: { type: 'string' },
455
+ category: { type: 'string' },
456
+ keyFindings: { type: 'array', items: { type: 'string' } },
457
+ relevanceScore: { type: 'number' }
458
+ }
459
+ },
460
+ description: 'Research topics for impact evaluation'
461
+ },
462
+ adrId: {
463
+ type: 'string',
464
+ description: 'ADR ID for update generation'
465
+ },
466
+ updateType: {
467
+ type: 'string',
468
+ enum: ['content', 'status', 'consequences', 'alternatives', 'deprecation'],
469
+ description: 'Type of ADR update to generate'
470
+ },
471
+ researchFindings: {
472
+ type: 'array',
473
+ items: {
474
+ type: 'object',
475
+ properties: {
476
+ finding: { type: 'string' },
477
+ evidence: { type: 'array', items: { type: 'string' } },
478
+ impact: { type: 'string' }
479
+ }
480
+ },
481
+ description: 'Research findings for update generation'
482
+ }
483
+ }
484
+ }
485
+ },
486
+ {
487
+ name: 'create_research_template',
488
+ description: 'Create a research template file for documenting findings',
489
+ inputSchema: {
490
+ type: 'object',
491
+ properties: {
492
+ title: {
493
+ type: 'string',
494
+ description: 'Title of the research'
495
+ },
496
+ category: {
497
+ type: 'string',
498
+ description: 'Research category',
499
+ default: 'general'
500
+ },
501
+ researchPath: {
502
+ type: 'string',
503
+ description: 'Path to research directory',
504
+ default: 'docs/research'
505
+ }
506
+ },
507
+ required: ['title']
508
+ }
509
+ },
510
+ {
511
+ name: 'request_action_confirmation',
512
+ description: 'Request confirmation before applying research-based changes',
513
+ inputSchema: {
514
+ type: 'object',
515
+ properties: {
516
+ action: {
517
+ type: 'string',
518
+ description: 'Description of the action to be performed'
519
+ },
520
+ details: {
521
+ type: 'string',
522
+ description: 'Detailed information about the action'
523
+ },
524
+ impact: {
525
+ type: 'string',
526
+ enum: ['low', 'medium', 'high', 'critical'],
527
+ description: 'Impact level of the action',
528
+ default: 'medium'
529
+ }
530
+ },
531
+ required: ['action', 'details']
532
+ }
533
+ },
534
+ {
535
+ name: 'generate_rules',
536
+ description: 'Generate architectural rules from ADRs and code patterns',
537
+ inputSchema: {
538
+ type: 'object',
539
+ properties: {
540
+ source: {
541
+ type: 'string',
542
+ enum: ['adrs', 'patterns', 'both'],
543
+ description: 'Source for rule generation',
544
+ default: 'both'
545
+ },
546
+ adrDirectory: {
547
+ type: 'string',
548
+ description: 'Directory containing ADR files',
549
+ default: 'docs/adrs'
550
+ },
551
+ projectPath: {
552
+ type: 'string',
553
+ description: 'Path to project for pattern analysis',
554
+ default: '.'
555
+ },
556
+ existingRules: {
557
+ type: 'array',
558
+ items: {
559
+ type: 'object',
560
+ properties: {
561
+ id: { type: 'string' },
562
+ name: { type: 'string' },
563
+ description: { type: 'string' }
564
+ }
565
+ },
566
+ description: 'Existing rules to avoid duplication'
567
+ },
568
+ outputFormat: {
569
+ type: 'string',
570
+ enum: ['json', 'yaml', 'both'],
571
+ description: 'Output format for rules',
572
+ default: 'json'
573
+ }
574
+ }
575
+ }
576
+ },
577
+ {
578
+ name: 'validate_rules',
579
+ description: 'Validate code against architectural rules',
580
+ inputSchema: {
581
+ type: 'object',
582
+ properties: {
583
+ filePath: {
584
+ type: 'string',
585
+ description: 'Path to file to validate'
586
+ },
587
+ fileContent: {
588
+ type: 'string',
589
+ description: 'Content to validate (alternative to filePath)'
590
+ },
591
+ fileName: {
592
+ type: 'string',
593
+ description: 'Name of file being validated (when using fileContent)'
594
+ },
595
+ rules: {
596
+ type: 'array',
597
+ items: {
598
+ type: 'object',
599
+ properties: {
600
+ id: { type: 'string' },
601
+ name: { type: 'string' },
602
+ description: { type: 'string' },
603
+ pattern: { type: 'string' },
604
+ severity: { type: 'string' },
605
+ message: { type: 'string' }
606
+ },
607
+ required: ['id', 'name', 'pattern', 'severity', 'message']
608
+ },
609
+ description: 'Rules to validate against'
610
+ },
611
+ validationType: {
612
+ type: 'string',
613
+ enum: ['file', 'function', 'component', 'module'],
614
+ description: 'Type of validation to perform',
615
+ default: 'file'
616
+ },
617
+ reportFormat: {
618
+ type: 'string',
619
+ enum: ['summary', 'detailed', 'json'],
620
+ description: 'Format for validation report',
621
+ default: 'detailed'
622
+ }
623
+ },
624
+ required: ['rules']
625
+ }
626
+ },
627
+ {
628
+ name: 'create_rule_set',
629
+ description: 'Create machine-readable rule set in JSON/YAML format',
630
+ inputSchema: {
631
+ type: 'object',
632
+ properties: {
633
+ name: {
634
+ type: 'string',
635
+ description: 'Name of the rule set'
636
+ },
637
+ description: {
638
+ type: 'string',
639
+ description: 'Description of the rule set',
640
+ default: 'Generated architectural rule set'
641
+ },
642
+ adrRules: {
643
+ type: 'array',
644
+ items: { type: 'object' },
645
+ description: 'Rules extracted from ADRs'
646
+ },
647
+ patternRules: {
648
+ type: 'array',
649
+ items: { type: 'object' },
650
+ description: 'Rules generated from code patterns'
651
+ },
652
+ rules: {
653
+ type: 'array',
654
+ items: { type: 'object' },
655
+ description: 'Additional rules to include'
656
+ },
657
+ outputFormat: {
658
+ type: 'string',
659
+ enum: ['json', 'yaml', 'both'],
660
+ description: 'Output format for rule set',
661
+ default: 'json'
662
+ },
663
+ author: {
664
+ type: 'string',
665
+ description: 'Author of the rule set',
666
+ default: 'MCP ADR Analysis Server'
667
+ }
668
+ },
669
+ required: ['name']
670
+ }
671
+ },
672
+ {
673
+ name: 'analyze_environment',
674
+ description: 'Analyze environment context and provide optimization recommendations',
675
+ inputSchema: {
676
+ type: 'object',
677
+ properties: {
678
+ projectPath: {
679
+ type: 'string',
680
+ description: 'Path to project directory',
681
+ default: '.'
682
+ },
683
+ adrDirectory: {
684
+ type: 'string',
685
+ description: 'Directory containing ADR files',
686
+ default: 'docs/adrs'
687
+ },
688
+ analysisType: {
689
+ type: 'string',
690
+ enum: ['specs', 'containerization', 'requirements', 'compliance', 'comprehensive'],
691
+ description: 'Type of environment analysis to perform',
692
+ default: 'comprehensive'
693
+ },
694
+ currentEnvironment: {
695
+ type: 'object',
696
+ description: 'Current environment specifications (for compliance analysis)'
697
+ },
698
+ requirements: {
699
+ type: 'object',
700
+ description: 'Environment requirements (for compliance analysis)'
701
+ },
702
+ industryStandards: {
703
+ type: 'array',
704
+ items: { type: 'string' },
705
+ description: 'Industry standards to assess compliance against'
706
+ }
707
+ }
708
+ }
709
+ },
710
+ {
711
+ name: 'generate_research_questions',
712
+ description: 'Generate context-aware research questions and create research tracking system',
713
+ inputSchema: {
714
+ type: 'object',
715
+ properties: {
716
+ analysisType: {
717
+ type: 'string',
718
+ enum: ['correlation', 'relevance', 'questions', 'tracking', 'comprehensive'],
719
+ description: 'Type of research analysis to perform',
720
+ default: 'comprehensive'
721
+ },
722
+ researchContext: {
723
+ type: 'object',
724
+ properties: {
725
+ topic: { type: 'string' },
726
+ category: { type: 'string' },
727
+ scope: { type: 'string' },
728
+ objectives: { type: 'array', items: { type: 'string' } },
729
+ constraints: { type: 'array', items: { type: 'string' } },
730
+ timeline: { type: 'string' }
731
+ },
732
+ description: 'Research context and objectives'
733
+ },
734
+ problems: {
735
+ type: 'array',
736
+ items: {
737
+ type: 'object',
738
+ properties: {
739
+ id: { type: 'string' },
740
+ description: { type: 'string' },
741
+ category: { type: 'string' },
742
+ severity: { type: 'string' },
743
+ context: { type: 'string' }
744
+ }
745
+ },
746
+ description: 'Problems to correlate with knowledge graph'
747
+ },
748
+ knowledgeGraph: {
749
+ type: 'object',
750
+ properties: {
751
+ technologies: { type: 'array', items: { type: 'object' } },
752
+ patterns: { type: 'array', items: { type: 'object' } },
753
+ adrs: { type: 'array', items: { type: 'object' } },
754
+ relationships: { type: 'array', items: { type: 'object' } }
755
+ },
756
+ description: 'Architectural knowledge graph'
757
+ },
758
+ relevantKnowledge: {
759
+ type: 'object',
760
+ properties: {
761
+ adrs: { type: 'array', items: { type: 'object' } },
762
+ patterns: { type: 'array', items: { type: 'object' } },
763
+ gaps: { type: 'array', items: { type: 'object' } },
764
+ opportunities: { type: 'array', items: { type: 'object' } }
765
+ },
766
+ description: 'Relevant knowledge for question generation'
767
+ },
768
+ researchQuestions: {
769
+ type: 'array',
770
+ items: {
771
+ type: 'object',
772
+ properties: {
773
+ id: { type: 'string' },
774
+ question: { type: 'string' },
775
+ type: { type: 'string' },
776
+ priority: { type: 'string' },
777
+ timeline: { type: 'string' },
778
+ methodology: { type: 'string' }
779
+ }
780
+ },
781
+ description: 'Research questions for task tracking'
782
+ },
783
+ currentProgress: {
784
+ type: 'array',
785
+ items: {
786
+ type: 'object',
787
+ properties: {
788
+ questionId: { type: 'string' },
789
+ status: { type: 'string' },
790
+ progress: { type: 'number' },
791
+ findings: { type: 'array', items: { type: 'string' } },
792
+ blockers: { type: 'array', items: { type: 'string' } }
793
+ }
794
+ },
795
+ description: 'Current research progress'
796
+ },
797
+ projectPath: {
798
+ type: 'string',
799
+ description: 'Path to project directory',
800
+ default: '.'
801
+ },
802
+ adrDirectory: {
803
+ type: 'string',
804
+ description: 'Directory containing ADR files',
805
+ default: 'docs/adrs'
806
+ }
807
+ }
808
+ }
809
+ },
810
+ {
811
+ name: 'analyze_deployment_progress',
812
+ description: 'Analyze deployment progress and verify completion with outcome rules',
813
+ inputSchema: {
814
+ type: 'object',
815
+ properties: {
816
+ analysisType: {
817
+ type: 'string',
818
+ enum: ['tasks', 'cicd', 'progress', 'completion', 'comprehensive'],
819
+ description: 'Type of deployment analysis to perform',
820
+ default: 'comprehensive'
821
+ },
822
+ adrDirectory: {
823
+ type: 'string',
824
+ description: 'Directory containing ADR files',
825
+ default: 'docs/adrs'
826
+ },
827
+ todoPath: {
828
+ type: 'string',
829
+ description: 'Path to todo.md file for task identification'
830
+ },
831
+ cicdLogs: {
832
+ type: 'string',
833
+ description: 'CI/CD pipeline logs for analysis'
834
+ },
835
+ pipelineConfig: {
836
+ type: 'string',
837
+ description: 'CI/CD pipeline configuration'
838
+ },
839
+ deploymentTasks: {
840
+ type: 'array',
841
+ items: {
842
+ type: 'object',
843
+ properties: {
844
+ taskId: { type: 'string' },
845
+ taskName: { type: 'string' },
846
+ status: { type: 'string' },
847
+ progress: { type: 'number' },
848
+ category: { type: 'string' },
849
+ priority: { type: 'string' },
850
+ verificationCriteria: { type: 'array', items: { type: 'string' } },
851
+ expectedOutcome: { type: 'string' }
852
+ }
853
+ },
854
+ description: 'Deployment tasks for progress calculation'
855
+ },
856
+ outcomeRules: {
857
+ type: 'array',
858
+ items: {
859
+ type: 'object',
860
+ properties: {
861
+ ruleId: { type: 'string' },
862
+ description: { type: 'string' },
863
+ criteria: { type: 'array', items: { type: 'string' } },
864
+ verificationMethod: { type: 'string' }
865
+ }
866
+ },
867
+ description: 'Outcome rules for completion verification'
868
+ },
869
+ actualOutcomes: {
870
+ type: 'array',
871
+ items: {
872
+ type: 'object',
873
+ properties: {
874
+ taskId: { type: 'string' },
875
+ outcome: { type: 'string' },
876
+ evidence: { type: 'array', items: { type: 'string' } },
877
+ timestamp: { type: 'string' }
878
+ }
879
+ },
880
+ description: 'Actual deployment outcomes'
881
+ },
882
+ cicdStatus: {
883
+ type: 'object',
884
+ description: 'CI/CD pipeline status data'
885
+ },
886
+ environmentStatus: {
887
+ type: 'object',
888
+ description: 'Environment status data'
889
+ }
890
+ }
891
+ }
892
+ }
893
+ ]
894
+ };
895
+ });
896
+ // Tool execution handler
897
+ this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
898
+ const { name, arguments: args } = request.params;
899
+ try {
900
+ let response;
901
+ switch (name) {
902
+ case 'analyze_project_ecosystem':
903
+ response = await this.analyzeProjectEcosystem(args);
904
+ break;
905
+ case 'get_architectural_context':
906
+ response = await this.getArchitecturalContext(args);
907
+ break;
908
+ case 'generate_adrs_from_prd':
909
+ response = await this.generateAdrsFromPrd(args);
910
+ break;
911
+ case 'generate_adr_todo':
912
+ response = await this.generateAdrTodo(args);
913
+ break;
914
+ case 'analyze_content_security':
915
+ response = await this.analyzeContentSecurity(args);
916
+ break;
917
+ case 'generate_content_masking':
918
+ response = await this.generateContentMasking(args);
919
+ break;
920
+ case 'configure_custom_patterns':
921
+ response = await this.configureCustomPatterns(args);
922
+ break;
923
+ case 'apply_basic_content_masking':
924
+ response = await this.applyBasicContentMasking(args);
925
+ break;
926
+ case 'validate_content_masking':
927
+ response = await this.validateContentMasking(args);
928
+ break;
929
+ case 'manage_cache':
930
+ response = await this.manageCache(args);
931
+ break;
932
+ case 'configure_output_masking':
933
+ response = await this.configureOutputMasking(args);
934
+ break;
935
+ case 'suggest_adrs':
936
+ response = await this.suggestAdrs(args);
937
+ break;
938
+ case 'generate_adr_from_decision':
939
+ response = await this.generateAdrFromDecision(args);
940
+ break;
941
+ case 'discover_existing_adrs':
942
+ response = await this.discoverExistingAdrs(args);
943
+ break;
944
+ case 'incorporate_research':
945
+ response = await this.incorporateResearch(args);
946
+ break;
947
+ case 'create_research_template':
948
+ response = await this.createResearchTemplate(args);
949
+ break;
950
+ case 'request_action_confirmation':
951
+ response = await this.requestActionConfirmation(args);
952
+ break;
953
+ case 'generate_rules':
954
+ response = await this.generateRules(args);
955
+ break;
956
+ case 'validate_rules':
957
+ response = await this.validateRules(args);
958
+ break;
959
+ case 'create_rule_set':
960
+ response = await this.createRuleSet(args);
961
+ break;
962
+ case 'analyze_environment':
963
+ response = await this.analyzeEnvironment(args);
964
+ break;
965
+ case 'generate_research_questions':
966
+ response = await this.generateResearchQuestions(args);
967
+ break;
968
+ case 'analyze_deployment_progress':
969
+ response = await this.analyzeDeploymentProgress(args);
970
+ break;
971
+ default:
972
+ throw new McpAdrError(`Unknown tool: ${name}`, 'UNKNOWN_TOOL');
973
+ }
974
+ // Apply content masking to response
975
+ return await this.applyOutputMasking(response);
976
+ }
977
+ catch (error) {
978
+ if (error instanceof McpAdrError) {
979
+ throw error;
980
+ }
981
+ throw new McpAdrError(`Tool execution failed: ${error instanceof Error ? error.message : String(error)}`, 'TOOL_EXECUTION_ERROR');
982
+ }
983
+ });
984
+ // Resources handler
985
+ this.server.setRequestHandler(ListResourcesRequestSchema, async () => {
986
+ return {
987
+ resources: [
988
+ {
989
+ uri: 'adr://architectural_knowledge_graph',
990
+ name: 'Architectural Knowledge Graph',
991
+ description: 'Complete architectural knowledge graph of the project',
992
+ mimeType: 'application/json'
993
+ },
994
+ {
995
+ uri: 'adr://analysis_report',
996
+ name: 'Analysis Report',
997
+ description: 'Comprehensive project analysis report',
998
+ mimeType: 'application/json'
999
+ },
1000
+ {
1001
+ uri: 'adr://adr_list',
1002
+ name: 'ADR List',
1003
+ description: 'List of all Architectural Decision Records',
1004
+ mimeType: 'application/json'
1005
+ }
1006
+ ]
1007
+ };
1008
+ });
1009
+ // Resource reading handler
1010
+ this.server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
1011
+ const { uri } = request.params;
1012
+ try {
1013
+ const response = await this.readResource(uri);
1014
+ return await this.applyOutputMasking(response);
1015
+ }
1016
+ catch (error) {
1017
+ if (error instanceof McpAdrError) {
1018
+ throw error;
1019
+ }
1020
+ throw new McpAdrError(`Resource reading failed: ${error instanceof Error ? error.message : String(error)}`, 'RESOURCE_ERROR');
1021
+ }
1022
+ });
1023
+ // Prompts handler
1024
+ this.server.setRequestHandler(ListPromptsRequestSchema, async () => {
1025
+ const { allPrompts } = await import('./prompts/index.js');
1026
+ return {
1027
+ prompts: allPrompts.map(prompt => ({
1028
+ name: prompt.name,
1029
+ description: prompt.description,
1030
+ arguments: prompt.arguments
1031
+ }))
1032
+ };
1033
+ });
1034
+ // Prompt execution handler
1035
+ this.server.setRequestHandler(GetPromptRequestSchema, async (request) => {
1036
+ const { name, arguments: args } = request.params;
1037
+ try {
1038
+ const { allPrompts } = await import('./prompts/index.js');
1039
+ const prompt = allPrompts.find(p => p.name === name);
1040
+ if (!prompt) {
1041
+ throw new McpAdrError(`Unknown prompt: ${name}`, 'UNKNOWN_PROMPT');
1042
+ }
1043
+ // Simple template rendering (replace {{variable}} with values)
1044
+ let renderedTemplate = prompt.template;
1045
+ if (args) {
1046
+ for (const [key, value] of Object.entries(args)) {
1047
+ const regex = new RegExp(`{{${key}}}`, 'g');
1048
+ renderedTemplate = renderedTemplate.replace(regex, String(value));
1049
+ }
1050
+ }
1051
+ const response = {
1052
+ description: prompt.description,
1053
+ messages: [
1054
+ {
1055
+ role: 'user',
1056
+ content: {
1057
+ type: 'text',
1058
+ text: renderedTemplate
1059
+ }
1060
+ }
1061
+ ]
1062
+ };
1063
+ return await this.applyOutputMasking(response);
1064
+ }
1065
+ catch (error) {
1066
+ if (error instanceof McpAdrError) {
1067
+ throw error;
1068
+ }
1069
+ throw new McpAdrError(`Prompt execution failed: ${error instanceof Error ? error.message : String(error)}`, 'PROMPT_EXECUTION_ERROR');
1070
+ }
1071
+ });
1072
+ }
1073
+ /**
1074
+ * Tool implementations
1075
+ */
1076
+ async analyzeProjectEcosystem(args) {
1077
+ // Use configured project path if not provided in args
1078
+ const projectPath = args.projectPath || this.config.projectPath;
1079
+ this.logger.info(`Analyzing project ecosystem at: ${projectPath}`);
1080
+ try {
1081
+ // Import utilities dynamically to avoid circular dependencies
1082
+ const { analyzeProjectStructure, readFileContent } = await import('./utils/file-system.js');
1083
+ const { generateAnalysisContext, generateComprehensiveAnalysisPrompt } = await import('./prompts/analysis-prompts.js');
1084
+ // Analyze project structure
1085
+ const projectStructure = await analyzeProjectStructure(projectPath);
1086
+ // Read key files for context
1087
+ let packageJsonContent;
1088
+ try {
1089
+ packageJsonContent = await readFileContent(`${projectPath}/package.json`);
1090
+ }
1091
+ catch {
1092
+ // package.json might not exist
1093
+ }
1094
+ // Generate analysis context
1095
+ const analysisContext = generateAnalysisContext(projectStructure);
1096
+ // Generate comprehensive analysis prompt
1097
+ const analysisPrompt = generateComprehensiveAnalysisPrompt(analysisContext, packageJsonContent);
1098
+ return {
1099
+ content: [
1100
+ {
1101
+ type: 'text',
1102
+ text: `Project ecosystem analysis for: ${projectPath}\n\nPlease analyze this project using the following prompt:\n\n${analysisPrompt}`
1103
+ }
1104
+ ]
1105
+ };
1106
+ }
1107
+ catch (error) {
1108
+ throw new McpAdrError(`Failed to analyze project ecosystem: ${error instanceof Error ? error.message : String(error)}`, 'ANALYSIS_ERROR');
1109
+ }
1110
+ }
1111
+ async getArchitecturalContext(args) {
1112
+ const { filePath } = args;
1113
+ try {
1114
+ const { analyzeProjectStructure } = await import('./utils/file-system.js');
1115
+ const { generateAnalysisContext, generatePatternDetectionPrompt } = await import('./prompts/analysis-prompts.js');
1116
+ // Determine project path
1117
+ const projectPath = filePath ? filePath.split('/').slice(0, -1).join('/') : process.cwd();
1118
+ // Analyze project structure
1119
+ const projectStructure = await analyzeProjectStructure(projectPath);
1120
+ const analysisContext = generateAnalysisContext(projectStructure);
1121
+ // Generate pattern detection prompt
1122
+ const patternPrompt = generatePatternDetectionPrompt(analysisContext);
1123
+ return {
1124
+ content: [
1125
+ {
1126
+ type: 'text',
1127
+ text: `Architectural context analysis${filePath ? ` for: ${filePath}` : ''}\n\nPlease analyze architectural patterns using the following prompt:\n\n${patternPrompt}`
1128
+ }
1129
+ ]
1130
+ };
1131
+ }
1132
+ catch (error) {
1133
+ throw new McpAdrError(`Failed to get architectural context: ${error instanceof Error ? error.message : String(error)}`, 'ANALYSIS_ERROR');
1134
+ }
1135
+ }
1136
+ async generateAdrsFromPrd(args) {
1137
+ const { prdPath } = args;
1138
+ const outputDirectory = args.outputDirectory || this.config.adrDirectory;
1139
+ this.logger.info(`Generating ADRs from PRD: ${prdPath} to ${outputDirectory}`);
1140
+ try {
1141
+ const { readFileContent, fileExists } = await import('./utils/file-system.js');
1142
+ // Check if PRD file exists
1143
+ if (!(await fileExists(prdPath))) {
1144
+ throw new McpAdrError(`PRD file not found: ${prdPath}`, 'FILE_NOT_FOUND');
1145
+ }
1146
+ // Read PRD content
1147
+ const prdContent = await readFileContent(prdPath);
1148
+ // Generate ADR creation prompt
1149
+ const adrPrompt = `
1150
+ # ADR Generation from PRD Request
1151
+
1152
+ Please analyze the following Product Requirements Document and generate Architectural Decision Records (ADRs).
1153
+
1154
+ ## PRD Content
1155
+ \`\`\`markdown
1156
+ ${prdContent}
1157
+ \`\`\`
1158
+
1159
+ ## Requirements
1160
+
1161
+ 1. **Extract Key Decisions**: Identify all architectural decisions implied or stated in the PRD
1162
+ 2. **Generate ADRs**: Create individual ADR files for each significant decision
1163
+ 3. **Follow ADR Format**: Use standard ADR template (title, status, context, decision, consequences)
1164
+ 4. **Number Sequentially**: Use format 001-decision-title.md, 002-next-decision.md, etc.
1165
+ 5. **Output Directory**: Place ADRs in ${outputDirectory}/
1166
+
1167
+ ## ADR Template Format
1168
+
1169
+ \`\`\`markdown
1170
+ # [Number]. [Title]
1171
+
1172
+ **Status**: [Proposed/Accepted/Deprecated/Superseded]
1173
+ **Date**: [YYYY-MM-DD]
1174
+
1175
+ ## Context
1176
+ [Describe the context and problem statement]
1177
+
1178
+ ## Decision
1179
+ [Describe the architectural decision]
1180
+
1181
+ ## Consequences
1182
+ [Describe the positive and negative consequences]
1183
+
1184
+ ## Implementation Plan
1185
+ [Optional: Steps to implement this decision]
1186
+ \`\`\`
1187
+
1188
+ Please provide:
1189
+ 1. List of identified architectural decisions
1190
+ 2. Generated ADR content for each decision
1191
+ 3. Recommended file names and structure
1192
+ 4. Implementation priority order
1193
+ `;
1194
+ return {
1195
+ content: [
1196
+ {
1197
+ type: 'text',
1198
+ text: `ADR generation from PRD: ${prdPath}\n\nPlease generate ADRs using the following prompt:\n\n${adrPrompt}`
1199
+ }
1200
+ ]
1201
+ };
1202
+ }
1203
+ catch (error) {
1204
+ throw new McpAdrError(`Failed to generate ADRs from PRD: ${error instanceof Error ? error.message : String(error)}`, 'GENERATION_ERROR');
1205
+ }
1206
+ }
1207
+ async generateAdrTodo(args) {
1208
+ const { scope = 'all' } = args;
1209
+ const adrDirectory = args.adrDirectory || this.config.adrDirectory;
1210
+ this.logger.info(`Generating todo from ADRs in: ${adrDirectory}`);
1211
+ try {
1212
+ const { findFiles } = await import('./utils/file-system.js');
1213
+ // Find all ADR files
1214
+ const adrFiles = await findFiles(process.cwd(), [`${adrDirectory}/**/*.md`], { includeContent: true });
1215
+ if (adrFiles.length === 0) {
1216
+ throw new McpAdrError(`No ADR files found in ${adrDirectory}`, 'NO_ADRS_FOUND');
1217
+ }
1218
+ // Prepare ADR content for analysis
1219
+ const adrContent = adrFiles.map(file => ({
1220
+ filename: file.name,
1221
+ path: file.path,
1222
+ content: file.content || ''
1223
+ }));
1224
+ // Generate todo creation prompt
1225
+ const todoPrompt = `
1226
+ # ADR Todo Generation Request
1227
+
1228
+ Please analyze the following Architectural Decision Records and generate a comprehensive todo.md file.
1229
+
1230
+ ## ADR Files
1231
+ ${adrContent.map(adr => `
1232
+ ### ${adr.filename}
1233
+ \`\`\`markdown
1234
+ ${adr.content.slice(0, 1500)}${adr.content.length > 1500 ? '\n... (truncated)' : ''}
1235
+ \`\`\`
1236
+ `).join('')}
1237
+
1238
+ ## Requirements
1239
+
1240
+ 1. **Extract Tasks**: Identify all implementation tasks from ADRs
1241
+ 2. **Categorize**: Group tasks by ADR and priority
1242
+ 3. **Status Detection**: Determine task completion status based on:
1243
+ - File existence checks
1244
+ - Code analysis hints
1245
+ - Implementation evidence
1246
+ 4. **Progress Tracking**: Calculate overall progress
1247
+ 5. **Scope Filter**: ${scope === 'all' ? 'Include all tasks' : `Focus on ${scope} tasks only`}
1248
+
1249
+ ## Todo.md Format
1250
+
1251
+ \`\`\`markdown
1252
+ # ADR Implementation Progress
1253
+
1254
+ **Last Updated**: [Date]
1255
+ **Overall Progress**: [X]% Complete
1256
+
1257
+ ## Summary
1258
+ - Total ADRs: [count]
1259
+ - Total Tasks: [count]
1260
+ - Completed: [count]
1261
+ - In Progress: [count]
1262
+ - Pending: [count]
1263
+
1264
+ ## Tasks by ADR
1265
+
1266
+ ### ADR-001: [Title]
1267
+ - [ ] Task 1 description
1268
+ - [x] Task 2 description (completed)
1269
+ - [/] Task 3 description (in progress)
1270
+
1271
+ ### ADR-002: [Title]
1272
+ - [ ] Task 1 description
1273
+ ...
1274
+ \`\`\`
1275
+
1276
+ Please provide:
1277
+ 1. Comprehensive task extraction from all ADRs
1278
+ 2. Status assessment for each task
1279
+ 3. Progress calculation
1280
+ 4. Prioritized task list
1281
+ 5. Implementation recommendations
1282
+ `;
1283
+ return {
1284
+ content: [
1285
+ {
1286
+ type: 'text',
1287
+ text: `ADR todo generation for: ${adrDirectory}\n\nPlease generate todo.md using the following prompt:\n\n${todoPrompt}`
1288
+ }
1289
+ ]
1290
+ };
1291
+ }
1292
+ catch (error) {
1293
+ throw new McpAdrError(`Failed to generate ADR todo: ${error instanceof Error ? error.message : String(error)}`, 'GENERATION_ERROR');
1294
+ }
1295
+ }
1296
+ /**
1297
+ * Content masking tool implementations
1298
+ */
1299
+ async analyzeContentSecurity(args) {
1300
+ const { analyzeContentSecurity } = await import('./tools/content-masking-tool.js');
1301
+ return await analyzeContentSecurity(args);
1302
+ }
1303
+ async generateContentMasking(args) {
1304
+ const { generateContentMasking } = await import('./tools/content-masking-tool.js');
1305
+ return await generateContentMasking(args);
1306
+ }
1307
+ async configureCustomPatterns(args) {
1308
+ const { configureCustomPatterns } = await import('./tools/content-masking-tool.js');
1309
+ return await configureCustomPatterns(args);
1310
+ }
1311
+ async applyBasicContentMasking(args) {
1312
+ const { applyBasicContentMasking } = await import('./tools/content-masking-tool.js');
1313
+ return await applyBasicContentMasking(args);
1314
+ }
1315
+ async validateContentMasking(args) {
1316
+ const { validateContentMasking } = await import('./tools/content-masking-tool.js');
1317
+ return await validateContentMasking(args);
1318
+ }
1319
+ async manageCache(args) {
1320
+ const { action, key } = args;
1321
+ try {
1322
+ const { clearCache, getCacheStats, cleanupCache, invalidateCache } = await import('./utils/cache.js');
1323
+ switch (action) {
1324
+ case 'clear': {
1325
+ await clearCache();
1326
+ return {
1327
+ content: [
1328
+ {
1329
+ type: 'text',
1330
+ text: '✅ Cache cleared successfully. All cached resources have been removed.'
1331
+ }
1332
+ ]
1333
+ };
1334
+ }
1335
+ case 'stats': {
1336
+ const stats = await getCacheStats();
1337
+ return {
1338
+ content: [
1339
+ {
1340
+ type: 'text',
1341
+ text: `# Cache Statistics
1342
+
1343
+ ## Overview
1344
+ - **Total Entries**: ${stats.totalEntries}
1345
+ - **Total Size**: ${(stats.totalSize / 1024).toFixed(2)} KB
1346
+ - **Oldest Entry**: ${stats.oldestEntry || 'None'}
1347
+ - **Newest Entry**: ${stats.newestEntry || 'None'}
1348
+
1349
+ ## Cache Directory
1350
+ \`.mcp-adr-cache/\`
1351
+
1352
+ ## Cache Types
1353
+ - **Knowledge Graph**: Architectural analysis results (TTL: 1 hour)
1354
+ - **Analysis Report**: Project analysis reports (TTL: 30 minutes)
1355
+ - **ADR List**: ADR inventory and metadata (TTL: 15 minutes)
1356
+
1357
+ ## Management
1358
+ Use \`manage_cache\` tool with different actions:
1359
+ - \`clear\`: Remove all cache entries
1360
+ - \`cleanup\`: Remove expired entries only
1361
+ - \`invalidate\`: Remove specific cache entry
1362
+ `
1363
+ }
1364
+ ]
1365
+ };
1366
+ }
1367
+ case 'cleanup': {
1368
+ const cleanedCount = await cleanupCache();
1369
+ return {
1370
+ content: [
1371
+ {
1372
+ type: 'text',
1373
+ text: `✅ Cache cleanup completed. Removed ${cleanedCount} expired entries.`
1374
+ }
1375
+ ]
1376
+ };
1377
+ }
1378
+ case 'invalidate': {
1379
+ if (!key) {
1380
+ throw new McpAdrError('Cache key is required for invalidate action', 'INVALID_INPUT');
1381
+ }
1382
+ await invalidateCache(key);
1383
+ return {
1384
+ content: [
1385
+ {
1386
+ type: 'text',
1387
+ text: `✅ Cache entry invalidated: ${key}`
1388
+ }
1389
+ ]
1390
+ };
1391
+ }
1392
+ default:
1393
+ throw new McpAdrError(`Unknown cache action: ${action}`, 'INVALID_INPUT');
1394
+ }
1395
+ }
1396
+ catch (error) {
1397
+ throw new McpAdrError(`Cache management failed: ${error instanceof Error ? error.message : String(error)}`, 'CACHE_ERROR');
1398
+ }
1399
+ }
1400
+ async configureOutputMasking(args) {
1401
+ const { action = 'get', enabled, strategy, customPatterns } = args;
1402
+ try {
1403
+ const { validateMaskingConfig } = await import('./utils/output-masking.js');
1404
+ switch (action) {
1405
+ case 'get': {
1406
+ return {
1407
+ content: [
1408
+ {
1409
+ type: 'text',
1410
+ text: `# Current Output Masking Configuration
1411
+
1412
+ ## Settings
1413
+ - **Enabled**: ${this.maskingConfig.enabled}
1414
+ - **Strategy**: ${this.maskingConfig.strategy}
1415
+ - **Custom Patterns**: ${this.maskingConfig.customPatterns?.length || 0} patterns
1416
+ - **Skip Patterns**: ${this.maskingConfig.skipPatterns?.length || 0} patterns
1417
+
1418
+ ## Available Strategies
1419
+ - **full**: Replace entire sensitive content with [REDACTED]
1420
+ - **partial**: Show safe prefix/suffix, mask middle (e.g., sk-...****)
1421
+ - **placeholder**: Replace with descriptive placeholders (e.g., <YOUR_API_KEY>)
1422
+ - **environment**: Replace with environment variable references (e.g., \${API_KEY})
1423
+
1424
+ ## Configuration
1425
+ Use \`configure_output_masking\` tool with:
1426
+ - \`action: "set"\` to update configuration
1427
+ - \`action: "reset"\` to restore defaults
1428
+
1429
+ ## Current Status
1430
+ ${this.maskingConfig.enabled ? '✅ Output masking is ACTIVE' : '⚠️ Output masking is DISABLED'}
1431
+ `
1432
+ }
1433
+ ]
1434
+ };
1435
+ }
1436
+ case 'set': {
1437
+ const newConfig = { ...this.maskingConfig };
1438
+ if (typeof enabled === 'boolean') {
1439
+ newConfig.enabled = enabled;
1440
+ }
1441
+ if (strategy && ['full', 'partial', 'placeholder', 'environment'].includes(strategy)) {
1442
+ newConfig.strategy = strategy;
1443
+ }
1444
+ if (Array.isArray(customPatterns)) {
1445
+ newConfig.customPatterns = customPatterns;
1446
+ }
1447
+ const validation = validateMaskingConfig(newConfig);
1448
+ if (!validation.isValid) {
1449
+ throw new McpAdrError(`Invalid masking configuration: ${validation.errors.join(', ')}`, 'INVALID_CONFIG');
1450
+ }
1451
+ this.maskingConfig = newConfig;
1452
+ return {
1453
+ content: [
1454
+ {
1455
+ type: 'text',
1456
+ text: `✅ Output masking configuration updated successfully!
1457
+
1458
+ ## New Settings
1459
+ - **Enabled**: ${newConfig.enabled}
1460
+ - **Strategy**: ${newConfig.strategy}
1461
+ - **Custom Patterns**: ${newConfig.customPatterns?.length || 0} patterns
1462
+
1463
+ ${newConfig.enabled ?
1464
+ '🔒 All MCP tool and resource outputs will now be masked according to the new configuration.' :
1465
+ '⚠️ Output masking is disabled. Sensitive information may be exposed in responses.'}
1466
+ `
1467
+ }
1468
+ ]
1469
+ };
1470
+ }
1471
+ case 'reset': {
1472
+ const { createMaskingConfig } = await import('./utils/output-masking.js');
1473
+ this.maskingConfig = createMaskingConfig();
1474
+ return {
1475
+ content: [
1476
+ {
1477
+ type: 'text',
1478
+ text: `✅ Output masking configuration reset to defaults!
1479
+
1480
+ ## Default Settings
1481
+ - **Enabled**: ${this.maskingConfig.enabled}
1482
+ - **Strategy**: ${this.maskingConfig.strategy}
1483
+ - **Custom Patterns**: ${this.maskingConfig.customPatterns?.length || 0} patterns
1484
+ - **Skip Patterns**: ${this.maskingConfig.skipPatterns?.length || 0} patterns
1485
+
1486
+ 🔒 Default masking is now active for all outputs.
1487
+ `
1488
+ }
1489
+ ]
1490
+ };
1491
+ }
1492
+ default:
1493
+ throw new McpAdrError(`Unknown masking action: ${action}`, 'INVALID_INPUT');
1494
+ }
1495
+ }
1496
+ catch (error) {
1497
+ throw new McpAdrError(`Output masking configuration failed: ${error instanceof Error ? error.message : String(error)}`, 'CONFIG_ERROR');
1498
+ }
1499
+ }
1500
+ /**
1501
+ * ADR suggestion tool implementations
1502
+ */
1503
+ async suggestAdrs(args) {
1504
+ const { suggestAdrs } = await import('./tools/adr-suggestion-tool.js');
1505
+ return await suggestAdrs(args);
1506
+ }
1507
+ async generateAdrFromDecision(args) {
1508
+ const { generateAdrFromDecision } = await import('./tools/adr-suggestion-tool.js');
1509
+ return await generateAdrFromDecision(args);
1510
+ }
1511
+ async discoverExistingAdrs(args) {
1512
+ const { discoverExistingAdrs } = await import('./tools/adr-suggestion-tool.js');
1513
+ return await discoverExistingAdrs(args);
1514
+ }
1515
+ /**
1516
+ * Research integration tool implementations
1517
+ */
1518
+ async incorporateResearch(args) {
1519
+ const { incorporateResearch } = await import('./tools/research-integration-tool.js');
1520
+ return await incorporateResearch(args);
1521
+ }
1522
+ async createResearchTemplate(args) {
1523
+ const { createResearchTemplate } = await import('./tools/research-integration-tool.js');
1524
+ return await createResearchTemplate(args);
1525
+ }
1526
+ async requestActionConfirmation(args) {
1527
+ const { requestActionConfirmation } = await import('./tools/research-integration-tool.js');
1528
+ return await requestActionConfirmation(args);
1529
+ }
1530
+ /**
1531
+ * Rule generation and validation tool implementations
1532
+ */
1533
+ async generateRules(args) {
1534
+ const { generateRules } = await import('./tools/rule-generation-tool.js');
1535
+ return await generateRules(args);
1536
+ }
1537
+ async validateRules(args) {
1538
+ const { validateRules } = await import('./tools/rule-generation-tool.js');
1539
+ return await validateRules(args);
1540
+ }
1541
+ async createRuleSet(args) {
1542
+ const { createRuleSet } = await import('./tools/rule-generation-tool.js');
1543
+ return await createRuleSet(args);
1544
+ }
1545
+ /**
1546
+ * Environment analysis tool implementation
1547
+ */
1548
+ async analyzeEnvironment(args) {
1549
+ const { analyzeEnvironment } = await import('./tools/environment-analysis-tool.js');
1550
+ return await analyzeEnvironment(args);
1551
+ }
1552
+ /**
1553
+ * Research question generation tool implementation
1554
+ */
1555
+ async generateResearchQuestions(args) {
1556
+ const { generateResearchQuestions } = await import('./tools/research-question-tool.js');
1557
+ return await generateResearchQuestions(args);
1558
+ }
1559
+ /**
1560
+ * Deployment analysis tool implementation
1561
+ */
1562
+ async analyzeDeploymentProgress(args) {
1563
+ const { analyzeDeploymentProgress } = await import('./tools/deployment-analysis-tool.js');
1564
+ return await analyzeDeploymentProgress(args);
1565
+ }
1566
+ /**
1567
+ * Apply content masking to MCP response
1568
+ */
1569
+ async applyOutputMasking(response) {
1570
+ try {
1571
+ return await maskMcpResponse(response, this.maskingConfig);
1572
+ }
1573
+ catch (error) {
1574
+ // If masking fails, log warning and return original response
1575
+ console.warn('Output masking failed:', error);
1576
+ return response;
1577
+ }
1578
+ }
1579
+ /**
1580
+ * Read MCP resource with caching
1581
+ */
1582
+ async readResource(uri) {
1583
+ try {
1584
+ const { getCachedOrGenerate } = await import('./utils/cache.js');
1585
+ // Parse URI to determine resource type and parameters
1586
+ const url = new globalThis.URL(uri);
1587
+ const resourceType = url.pathname.replace('/', '');
1588
+ const params = Object.fromEntries(url.searchParams.entries());
1589
+ switch (resourceType) {
1590
+ case 'architectural_knowledge_graph': {
1591
+ const { generateArchitecturalKnowledgeGraph } = await import('./resources/index.js');
1592
+ const projectPath = params['projectPath'] || process.cwd();
1593
+ const result = await getCachedOrGenerate(`knowledge-graph:${projectPath}`, () => generateArchitecturalKnowledgeGraph(projectPath), { ttl: 3600 });
1594
+ return {
1595
+ contents: [
1596
+ {
1597
+ uri,
1598
+ mimeType: result.contentType,
1599
+ text: JSON.stringify(result.data, null, 2)
1600
+ }
1601
+ ]
1602
+ };
1603
+ }
1604
+ case 'analysis_report': {
1605
+ const { generateAnalysisReport } = await import('./resources/index.js');
1606
+ const projectPath = params['projectPath'] || process.cwd();
1607
+ const focusAreas = params['focusAreas'] ? params['focusAreas'].split(',') : undefined;
1608
+ const result = await getCachedOrGenerate(`analysis-report:${projectPath}:${focusAreas?.join(',') || ''}`, () => generateAnalysisReport(projectPath, focusAreas), { ttl: 1800 });
1609
+ return {
1610
+ contents: [
1611
+ {
1612
+ uri,
1613
+ mimeType: result.contentType,
1614
+ text: JSON.stringify(result.data, null, 2)
1615
+ }
1616
+ ]
1617
+ };
1618
+ }
1619
+ case 'adr_list': {
1620
+ const { generateAdrList } = await import('./resources/index.js');
1621
+ const adrDirectory = params['adrDirectory'] || 'docs/adrs';
1622
+ const result = await getCachedOrGenerate(`adr-list:${adrDirectory}`, () => generateAdrList(adrDirectory), { ttl: 900 });
1623
+ return {
1624
+ contents: [
1625
+ {
1626
+ uri,
1627
+ mimeType: result.contentType,
1628
+ text: JSON.stringify(result.data, null, 2)
1629
+ }
1630
+ ]
1631
+ };
1632
+ }
1633
+ default:
1634
+ throw new McpAdrError(`Unknown resource type: ${resourceType}`, 'UNKNOWN_RESOURCE');
1635
+ }
1636
+ }
1637
+ catch (error) {
1638
+ if (error instanceof McpAdrError) {
1639
+ throw error;
1640
+ }
1641
+ throw new McpAdrError(`Failed to read resource: ${error instanceof Error ? error.message : String(error)}`, 'RESOURCE_ERROR');
1642
+ }
1643
+ }
1644
+ /**
1645
+ * Start the server
1646
+ */
1647
+ async start() {
1648
+ // Validate configuration before starting
1649
+ await this.validateConfiguration();
1650
+ const transport = new StdioServerTransport();
1651
+ await this.server.connect(transport);
1652
+ // Keep the process alive
1653
+ process.on('SIGINT', async () => {
1654
+ await this.server.close();
1655
+ process.exit(0);
1656
+ });
1657
+ }
1658
+ }
1659
+ /**
1660
+ * Main execution
1661
+ */
1662
+ async function main() {
1663
+ const args = process.argv.slice(2);
1664
+ // Handle command line arguments
1665
+ if (args.includes('--help') || args.includes('-h')) {
1666
+ console.log(`
1667
+ MCP ADR Analysis Server v${SERVER_INFO.version}
1668
+
1669
+ Usage: mcp-adr-analysis-server [options]
1670
+
1671
+ Options:
1672
+ --help, -h Show this help message
1673
+ --version, -v Show version information
1674
+ --test Run health check and exit
1675
+ --config Show configuration and exit
1676
+
1677
+ Environment Variables:
1678
+ PROJECT_PATH Path to project directory (default: current directory)
1679
+ ADR_DIRECTORY ADR directory relative to project (default: docs/adrs)
1680
+ LOG_LEVEL Logging level: DEBUG, INFO, WARN, ERROR (default: INFO)
1681
+ CACHE_ENABLED Enable caching: true, false (default: true)
1682
+
1683
+ Examples:
1684
+ mcp-adr-analysis-server # Start MCP server
1685
+ PROJECT_PATH=/path/to/project mcp-adr-analysis-server
1686
+ mcp-adr-analysis-server --test # Health check
1687
+ `);
1688
+ process.exit(0);
1689
+ }
1690
+ if (args.includes('--version') || args.includes('-v')) {
1691
+ console.log(`MCP ADR Analysis Server v${SERVER_INFO.version}`);
1692
+ process.exit(0);
1693
+ }
1694
+ try {
1695
+ const server = new McpAdrAnalysisServer();
1696
+ if (args.includes('--test')) {
1697
+ console.log('🔍 Running health check...');
1698
+ await server.healthCheck();
1699
+ console.log('✅ Health check passed - server can start successfully');
1700
+ process.exit(0);
1701
+ }
1702
+ if (args.includes('--config')) {
1703
+ console.log('📋 Server configuration validated');
1704
+ process.exit(0);
1705
+ }
1706
+ // Normal server startup
1707
+ await server.start();
1708
+ }
1709
+ catch (error) {
1710
+ console.error('❌ MCP server failed to start');
1711
+ console.error('Error:', error instanceof Error ? error.message : String(error));
1712
+ process.exit(1);
1713
+ }
1714
+ }
1715
+ // Start the server if this file is run directly
1716
+ if (import.meta.url === `file://${process.argv[1]}`) {
1717
+ main().catch((error) => {
1718
+ console.error('Unhandled error:', error);
1719
+ process.exit(1);
1720
+ });
1721
+ }
1722
+ //# sourceMappingURL=index.js.map