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.
- package/LICENSE +21 -0
- package/README.md +608 -0
- package/dist/src/index.d.ts +10 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +1722 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/prompts/adr-suggestion-prompts.d.ts +24 -0
- package/dist/src/prompts/adr-suggestion-prompts.d.ts.map +1 -0
- package/dist/src/prompts/adr-suggestion-prompts.js +383 -0
- package/dist/src/prompts/adr-suggestion-prompts.js.map +1 -0
- package/dist/src/prompts/analysis-prompts.d.ts +24 -0
- package/dist/src/prompts/analysis-prompts.d.ts.map +1 -0
- package/dist/src/prompts/analysis-prompts.js +489 -0
- package/dist/src/prompts/analysis-prompts.js.map +1 -0
- package/dist/src/prompts/deployment-analysis-prompts.d.ts +54 -0
- package/dist/src/prompts/deployment-analysis-prompts.d.ts.map +1 -0
- package/dist/src/prompts/deployment-analysis-prompts.js +712 -0
- package/dist/src/prompts/deployment-analysis-prompts.js.map +1 -0
- package/dist/src/prompts/environment-analysis-prompts.d.ts +34 -0
- package/dist/src/prompts/environment-analysis-prompts.d.ts.map +1 -0
- package/dist/src/prompts/environment-analysis-prompts.js +724 -0
- package/dist/src/prompts/environment-analysis-prompts.js.map +1 -0
- package/dist/src/prompts/index.d.ts +43 -0
- package/dist/src/prompts/index.d.ts.map +1 -0
- package/dist/src/prompts/index.js +384 -0
- package/dist/src/prompts/index.js.map +1 -0
- package/dist/src/prompts/research-integration-prompts.d.ts +43 -0
- package/dist/src/prompts/research-integration-prompts.d.ts.map +1 -0
- package/dist/src/prompts/research-integration-prompts.js +398 -0
- package/dist/src/prompts/research-integration-prompts.js.map +1 -0
- package/dist/src/prompts/research-question-prompts.d.ts +75 -0
- package/dist/src/prompts/research-question-prompts.d.ts.map +1 -0
- package/dist/src/prompts/research-question-prompts.js +695 -0
- package/dist/src/prompts/research-question-prompts.js.map +1 -0
- package/dist/src/prompts/rule-generation-prompts.d.ts +63 -0
- package/dist/src/prompts/rule-generation-prompts.d.ts.map +1 -0
- package/dist/src/prompts/rule-generation-prompts.js +630 -0
- package/dist/src/prompts/rule-generation-prompts.js.map +1 -0
- package/dist/src/prompts/security-prompts.d.ts +23 -0
- package/dist/src/prompts/security-prompts.d.ts.map +1 -0
- package/dist/src/prompts/security-prompts.js +287 -0
- package/dist/src/prompts/security-prompts.js.map +1 -0
- package/dist/src/resources/index.d.ts +24 -0
- package/dist/src/resources/index.d.ts.map +1 -0
- package/dist/src/resources/index.js +458 -0
- package/dist/src/resources/index.js.map +1 -0
- package/dist/src/tools/adr-suggestion-tool.d.ts +40 -0
- package/dist/src/tools/adr-suggestion-tool.d.ts.map +1 -0
- package/dist/src/tools/adr-suggestion-tool.js +338 -0
- package/dist/src/tools/adr-suggestion-tool.js.map +1 -0
- package/dist/src/tools/content-masking-tool.d.ts +52 -0
- package/dist/src/tools/content-masking-tool.d.ts.map +1 -0
- package/dist/src/tools/content-masking-tool.js +206 -0
- package/dist/src/tools/content-masking-tool.js.map +1 -0
- package/dist/src/tools/deployment-analysis-tool.d.ts +39 -0
- package/dist/src/tools/deployment-analysis-tool.d.ts.map +1 -0
- package/dist/src/tools/deployment-analysis-tool.js +310 -0
- package/dist/src/tools/deployment-analysis-tool.js.map +1 -0
- package/dist/src/tools/environment-analysis-tool.d.ts +16 -0
- package/dist/src/tools/environment-analysis-tool.d.ts.map +1 -0
- package/dist/src/tools/environment-analysis-tool.js +298 -0
- package/dist/src/tools/environment-analysis-tool.js.map +1 -0
- package/dist/src/tools/research-integration-tool.d.ts +44 -0
- package/dist/src/tools/research-integration-tool.d.ts.map +1 -0
- package/dist/src/tools/research-integration-tool.js +429 -0
- package/dist/src/tools/research-integration-tool.js.map +1 -0
- package/dist/src/tools/research-question-tool.d.ts +55 -0
- package/dist/src/tools/research-question-tool.d.ts.map +1 -0
- package/dist/src/tools/research-question-tool.js +333 -0
- package/dist/src/tools/research-question-tool.js.map +1 -0
- package/dist/src/tools/rule-generation-tool.d.ts +49 -0
- package/dist/src/tools/rule-generation-tool.d.ts.map +1 -0
- package/dist/src/tools/rule-generation-tool.js +432 -0
- package/dist/src/tools/rule-generation-tool.js.map +1 -0
- package/dist/src/types/index.d.ts +531 -0
- package/dist/src/types/index.d.ts.map +1 -0
- package/dist/src/types/index.js +129 -0
- package/dist/src/types/index.js.map +1 -0
- package/dist/src/utils/adr-suggestions.d.ts +104 -0
- package/dist/src/utils/adr-suggestions.d.ts.map +1 -0
- package/dist/src/utils/adr-suggestions.js +228 -0
- package/dist/src/utils/adr-suggestions.js.map +1 -0
- package/dist/src/utils/cache.d.ts +51 -0
- package/dist/src/utils/cache.d.ts.map +1 -0
- package/dist/src/utils/cache.js +243 -0
- package/dist/src/utils/cache.js.map +1 -0
- package/dist/src/utils/config.d.ts +65 -0
- package/dist/src/utils/config.d.ts.map +1 -0
- package/dist/src/utils/config.js +118 -0
- package/dist/src/utils/config.js.map +1 -0
- package/dist/src/utils/content-masking.d.ts +79 -0
- package/dist/src/utils/content-masking.d.ts.map +1 -0
- package/dist/src/utils/content-masking.js +203 -0
- package/dist/src/utils/content-masking.js.map +1 -0
- package/dist/src/utils/deployment-analysis.d.ts +67 -0
- package/dist/src/utils/deployment-analysis.d.ts.map +1 -0
- package/dist/src/utils/deployment-analysis.js +263 -0
- package/dist/src/utils/deployment-analysis.js.map +1 -0
- package/dist/src/utils/environment-analysis.d.ts +76 -0
- package/dist/src/utils/environment-analysis.d.ts.map +1 -0
- package/dist/src/utils/environment-analysis.js +329 -0
- package/dist/src/utils/environment-analysis.js.map +1 -0
- package/dist/src/utils/file-system.d.ts +63 -0
- package/dist/src/utils/file-system.d.ts.map +1 -0
- package/dist/src/utils/file-system.js +189 -0
- package/dist/src/utils/file-system.js.map +1 -0
- package/dist/src/utils/output-masking.d.ts +45 -0
- package/dist/src/utils/output-masking.d.ts.map +1 -0
- package/dist/src/utils/output-masking.js +200 -0
- package/dist/src/utils/output-masking.js.map +1 -0
- package/dist/src/utils/research-documentation.d.ts +58 -0
- package/dist/src/utils/research-documentation.d.ts.map +1 -0
- package/dist/src/utils/research-documentation.js +438 -0
- package/dist/src/utils/research-documentation.js.map +1 -0
- package/dist/src/utils/research-integration.d.ts +89 -0
- package/dist/src/utils/research-integration.d.ts.map +1 -0
- package/dist/src/utils/research-integration.js +432 -0
- package/dist/src/utils/research-integration.js.map +1 -0
- package/dist/src/utils/research-questions.d.ts +97 -0
- package/dist/src/utils/research-questions.d.ts.map +1 -0
- package/dist/src/utils/research-questions.js +319 -0
- package/dist/src/utils/research-questions.js.map +1 -0
- package/dist/src/utils/rule-format.d.ts +76 -0
- package/dist/src/utils/rule-format.d.ts.map +1 -0
- package/dist/src/utils/rule-format.js +257 -0
- package/dist/src/utils/rule-format.js.map +1 -0
- package/dist/src/utils/rule-generation.d.ts +86 -0
- package/dist/src/utils/rule-generation.d.ts.map +1 -0
- package/dist/src/utils/rule-generation.js +330 -0
- package/dist/src/utils/rule-generation.js.map +1 -0
- 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
|