@utaba/ucm-mcp-server 1.0.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 (80) hide show
  1. package/LICENSE +29 -0
  2. package/README.md +79 -0
  3. package/dist/clients/UcmApiClient.d.ts +53 -0
  4. package/dist/clients/UcmApiClient.js +297 -0
  5. package/dist/index.d.ts +3 -0
  6. package/dist/index.js +68 -0
  7. package/dist/interfaces/ILogger.d.ts +8 -0
  8. package/dist/interfaces/ILogger.js +4 -0
  9. package/dist/interfaces/IMcpTool.d.ts +7 -0
  10. package/dist/interfaces/IMcpTool.js +3 -0
  11. package/dist/logging/ConsoleLogger.d.ts +16 -0
  12. package/dist/logging/ConsoleLogger.js +45 -0
  13. package/dist/logging/LoggerFactory.d.ts +9 -0
  14. package/dist/logging/LoggerFactory.js +12 -0
  15. package/dist/server/McpConfig.d.ts +26 -0
  16. package/dist/server/McpConfig.js +93 -0
  17. package/dist/server/McpHandler.d.ts +12 -0
  18. package/dist/server/McpHandler.js +69 -0
  19. package/dist/server/McpServer.d.ts +15 -0
  20. package/dist/server/McpServer.js +49 -0
  21. package/dist/server/ToolRegistry.d.ts +22 -0
  22. package/dist/server/ToolRegistry.js +85 -0
  23. package/dist/tools/artifacts/GetArtifactController.d.ts +34 -0
  24. package/dist/tools/artifacts/GetArtifactController.js +397 -0
  25. package/dist/tools/artifacts/GetLatestController.d.ts +39 -0
  26. package/dist/tools/artifacts/GetLatestController.js +469 -0
  27. package/dist/tools/artifacts/ListVersionsController.d.ts +43 -0
  28. package/dist/tools/artifacts/ListVersionsController.js +530 -0
  29. package/dist/tools/artifacts/PublishArtifactController.d.ts +37 -0
  30. package/dist/tools/artifacts/PublishArtifactController.js +605 -0
  31. package/dist/tools/base/BaseToolController.d.ts +16 -0
  32. package/dist/tools/base/BaseToolController.js +32 -0
  33. package/dist/tools/core/DeleteArtifactTool.d.ts +11 -0
  34. package/dist/tools/core/DeleteArtifactTool.js +82 -0
  35. package/dist/tools/core/GetArtifactTool.d.ts +13 -0
  36. package/dist/tools/core/GetArtifactTool.js +125 -0
  37. package/dist/tools/core/GetArtifactVersionsTool.d.ts +11 -0
  38. package/dist/tools/core/GetArtifactVersionsTool.js +63 -0
  39. package/dist/tools/core/GetChunkTool.d.ts +11 -0
  40. package/dist/tools/core/GetChunkTool.js +56 -0
  41. package/dist/tools/core/ListArtifactsTool.d.ts +11 -0
  42. package/dist/tools/core/ListArtifactsTool.js +84 -0
  43. package/dist/tools/core/PublishArtifactFromFileTool.d.ts +15 -0
  44. package/dist/tools/core/PublishArtifactFromFileTool.js +256 -0
  45. package/dist/tools/core/PublishArtifactTool.d.ts +13 -0
  46. package/dist/tools/core/PublishArtifactTool.js +197 -0
  47. package/dist/tools/discovery/BrowseCategoriesController.d.ts +25 -0
  48. package/dist/tools/discovery/BrowseCategoriesController.js +400 -0
  49. package/dist/tools/discovery/FindByPurposeController.d.ts +12 -0
  50. package/dist/tools/discovery/FindByPurposeController.js +131 -0
  51. package/dist/tools/discovery/ListAuthorsController.d.ts +20 -0
  52. package/dist/tools/discovery/ListAuthorsController.js +274 -0
  53. package/dist/tools/discovery/SearchArtifactsController.d.ts +14 -0
  54. package/dist/tools/discovery/SearchArtifactsController.js +226 -0
  55. package/dist/tools/list/ListNamespaceController.d.ts +1 -0
  56. package/dist/tools/list/ListNamespaceController.js +8 -0
  57. package/dist/tools/navigation/ExploreNamespaceController.d.ts +35 -0
  58. package/dist/tools/navigation/ExploreNamespaceController.js +548 -0
  59. package/dist/tools/utility/AuthorIndexTool.d.ts +11 -0
  60. package/dist/tools/utility/AuthorIndexTool.js +48 -0
  61. package/dist/tools/utility/HealthCheckController.d.ts +11 -0
  62. package/dist/tools/utility/HealthCheckController.js +56 -0
  63. package/dist/tools/utility/ListRepositoriesTool.d.ts +11 -0
  64. package/dist/tools/utility/ListRepositoriesTool.js +70 -0
  65. package/dist/tools/utility/QuickstartTool.d.ts +11 -0
  66. package/dist/tools/utility/QuickstartTool.js +36 -0
  67. package/dist/tools/utility/ValidatePathController.d.ts +30 -0
  68. package/dist/tools/utility/ValidatePathController.js +465 -0
  69. package/dist/types/UcmApiTypes.d.ts +40 -0
  70. package/dist/types/UcmApiTypes.js +4 -0
  71. package/dist/utils/McpErrorHandler.d.ts +25 -0
  72. package/dist/utils/McpErrorHandler.js +67 -0
  73. package/dist/utils/PathUtils.d.ts +61 -0
  74. package/dist/utils/PathUtils.js +178 -0
  75. package/dist/utils/ResponseChunker.d.ts +25 -0
  76. package/dist/utils/ResponseChunker.js +79 -0
  77. package/dist/utils/ValidationUtils.d.ts +10 -0
  78. package/dist/utils/ValidationUtils.js +50 -0
  79. package/package.json +37 -0
  80. package/package.json.backup +37 -0
@@ -0,0 +1,397 @@
1
+ import { BaseToolController } from '../base/BaseToolController.js';
2
+ import { ValidationUtils } from '../../utils/ValidationUtils.js';
3
+ import { parsePath } from '../../utils/PathUtils.js';
4
+ export class GetArtifactController extends BaseToolController {
5
+ constructor(ucmClient, logger) {
6
+ super(ucmClient, logger);
7
+ }
8
+ get name() {
9
+ return 'mcp_ucm_get_artifact';
10
+ }
11
+ get description() {
12
+ return 'Retrieve a specific UCM artifact with its content, metadata, and optional examples';
13
+ }
14
+ get inputSchema() {
15
+ return {
16
+ type: 'object',
17
+ properties: {
18
+ path: {
19
+ type: 'string',
20
+ description: 'Full artifact path (e.g., "utaba/commands/create-user/typescript/1.0.0" or "utaba/commands/create-user/1.0.0")',
21
+ minLength: 5,
22
+ maxLength: 200
23
+ },
24
+ includeContent: {
25
+ type: 'boolean',
26
+ default: true,
27
+ description: 'Include the artifact source content in the response'
28
+ },
29
+ includeMetadata: {
30
+ type: 'boolean',
31
+ default: true,
32
+ description: 'Include comprehensive metadata about the artifact'
33
+ },
34
+ includeExamples: {
35
+ type: 'boolean',
36
+ default: false,
37
+ description: 'Include usage examples and documentation'
38
+ },
39
+ includeDependencies: {
40
+ type: 'boolean',
41
+ default: false,
42
+ description: 'Include detailed dependency information'
43
+ },
44
+ includeVersionHistory: {
45
+ type: 'boolean',
46
+ default: false,
47
+ description: 'Include version history for this artifact'
48
+ },
49
+ format: {
50
+ type: 'string',
51
+ enum: ['full', 'summary', 'content-only', 'metadata-only'],
52
+ default: 'full',
53
+ description: 'Response format level'
54
+ }
55
+ },
56
+ required: ['path']
57
+ };
58
+ }
59
+ async handleExecute(params) {
60
+ const { path, includeContent = true, includeMetadata = true, includeExamples = false, includeDependencies = false, includeVersionHistory = false, format = 'full' } = params;
61
+ // Validate and sanitize the artifact path
62
+ ValidationUtils.validateArtifactPath(path);
63
+ this.logger.debug('GetArtifactController', `Retrieving artifact: ${path}`);
64
+ try {
65
+ // Parse the path to get component parts
66
+ const parsed = parsePath(path);
67
+ // Get the artifact from UCM API
68
+ const artifact = await this.ucmClient.getArtifact(parsed.author, parsed.category, parsed.subcategory, parsed.filename, parsed.version);
69
+ if (!artifact) {
70
+ throw new Error(`Artifact not found at path: ${path}`);
71
+ }
72
+ // Build response based on requested format and includes
73
+ const response = await this.buildArtifactResponse(artifact, {
74
+ includeContent,
75
+ includeMetadata,
76
+ includeExamples,
77
+ includeDependencies,
78
+ includeVersionHistory,
79
+ format
80
+ });
81
+ this.logger.info('GetArtifactController', `Successfully retrieved artifact: ${path}`);
82
+ return response;
83
+ }
84
+ catch (error) {
85
+ this.logger.error('GetArtifactController', `Failed to retrieve artifact: ${path}`, '', error);
86
+ throw error;
87
+ }
88
+ }
89
+ async buildArtifactResponse(artifact, options) {
90
+ const { includeContent, includeMetadata, includeExamples, includeDependencies, includeVersionHistory, format } = options;
91
+ // Base response structure
92
+ const response = {
93
+ path: artifact.path,
94
+ id: artifact.id
95
+ };
96
+ // Handle different format types
97
+ switch (format) {
98
+ case 'content-only':
99
+ if (artifact.content) {
100
+ response.content = artifact.content;
101
+ }
102
+ response.contentType = this.detectContentType(artifact);
103
+ break;
104
+ case 'metadata-only':
105
+ if (includeMetadata && artifact.metadata) {
106
+ response.metadata = this.enrichMetadata(artifact.metadata);
107
+ }
108
+ break;
109
+ case 'summary':
110
+ response.name = artifact.metadata?.name || 'Unknown';
111
+ response.description = artifact.metadata?.description || '';
112
+ response.author = artifact.metadata?.author || '';
113
+ response.category = artifact.metadata?.category || '';
114
+ response.version = artifact.metadata?.version || '';
115
+ response.lastUpdated = artifact.lastUpdated;
116
+ break;
117
+ default: // 'full'
118
+ // Include basic artifact information
119
+ response.name = artifact.metadata?.name || 'Unknown';
120
+ response.author = artifact.metadata?.author || '';
121
+ response.category = artifact.metadata?.category || '';
122
+ response.subcategory = artifact.metadata?.subcategory || '';
123
+ response.technology = artifact.metadata?.technology || null;
124
+ response.version = artifact.metadata?.version || '';
125
+ response.lastUpdated = artifact.lastUpdated;
126
+ response.publishedAt = artifact.publishedAt;
127
+ // Include content if requested
128
+ if (includeContent && artifact.content) {
129
+ response.content = artifact.content;
130
+ response.contentType = this.detectContentType(artifact);
131
+ response.contentSize = artifact.content.length;
132
+ }
133
+ // Include metadata if requested
134
+ if (includeMetadata && artifact.metadata) {
135
+ response.metadata = this.enrichMetadata(artifact.metadata);
136
+ }
137
+ // Include examples if requested
138
+ if (includeExamples && artifact.examples) {
139
+ response.examples = this.processExamples(artifact.examples);
140
+ }
141
+ // Include dependencies if requested
142
+ if (includeDependencies && artifact.metadata?.dependencies) {
143
+ response.dependencies = await this.enrichDependencies(artifact.metadata.dependencies);
144
+ }
145
+ // Include version history if requested
146
+ if (includeVersionHistory) {
147
+ response.versionHistory = await this.getVersionHistory(artifact.path);
148
+ }
149
+ // Add usage and statistics
150
+ response.usage = {
151
+ downloadCount: this.getDownloadCount(artifact),
152
+ rating: this.calculateRating(artifact),
153
+ lastAccessed: this.getLastAccessTime()
154
+ };
155
+ // Add related artifacts
156
+ response.related = await this.getRelatedArtifacts(artifact);
157
+ break;
158
+ }
159
+ // Add retrieval metadata
160
+ response.retrievalMetadata = {
161
+ timestamp: new Date().toISOString(),
162
+ format,
163
+ includedSections: this.getIncludedSections(options),
164
+ cacheable: true,
165
+ sourceApi: 'UCM-v1'
166
+ };
167
+ return response;
168
+ }
169
+ enrichMetadata(metadata) {
170
+ return {
171
+ ...metadata,
172
+ // Add computed fields
173
+ isLatestVersion: this.isLatestVersion(metadata.version),
174
+ qualityScore: this.calculateQualityScore(metadata),
175
+ complexity: this.estimateComplexity(metadata),
176
+ maturityLevel: this.assessMaturityLevel(metadata),
177
+ // Sanitize sensitive data
178
+ dependencies: metadata.dependencies ? {
179
+ ...metadata.dependencies,
180
+ // Remove any potential secrets from dependency configs
181
+ external: this.sanitizeExternalDependencies(metadata.dependencies.external)
182
+ } : undefined
183
+ };
184
+ }
185
+ processExamples(examples) {
186
+ return examples.map((example, index) => ({
187
+ id: index + 1,
188
+ title: example.title || `Example ${index + 1}`,
189
+ description: example.description || '',
190
+ code: example.code || example.content || '',
191
+ language: example.language || this.detectLanguage(example.code),
192
+ complexity: example.complexity || 'intermediate',
193
+ category: example.category || 'usage',
194
+ runnable: example.runnable !== false, // Default to true
195
+ dependencies: example.dependencies || []
196
+ }));
197
+ }
198
+ async enrichDependencies(dependencies) {
199
+ const enriched = {
200
+ services: dependencies.services || [],
201
+ commands: dependencies.commands || [],
202
+ external: dependencies.external || {}
203
+ };
204
+ // Add dependency resolution information
205
+ enriched.resolution = {
206
+ resolvable: await this.checkDependencyResolution(dependencies),
207
+ missing: await this.findMissingDependencies(dependencies),
208
+ conflicts: await this.detectDependencyConflicts(dependencies)
209
+ };
210
+ return enriched;
211
+ }
212
+ async getVersionHistory(artifactPath) {
213
+ try {
214
+ // Parse the path to get component parts
215
+ const parsed = parsePath(artifactPath);
216
+ const versions = await this.ucmClient.getArtifactVersions(parsed.author, parsed.category, parsed.subcategory);
217
+ return versions.map(version => ({
218
+ version: version.metadata?.version || '',
219
+ publishedAt: version.publishedAt,
220
+ contractVersion: version.metadata?.contractVersion,
221
+ changesSummary: this.generateChangesSummary(version),
222
+ isBreaking: this.isBreakingChange(version),
223
+ downloadCount: this.getDownloadCount(version)
224
+ }));
225
+ }
226
+ catch (error) {
227
+ this.logger.warn('GetArtifactController', 'Failed to get version history', '', error);
228
+ return [];
229
+ }
230
+ }
231
+ async getRelatedArtifacts(artifact) {
232
+ try {
233
+ // Find related artifacts based on category, author, and tags
234
+ const searchTerms = [
235
+ artifact.metadata?.category,
236
+ artifact.metadata?.subcategory,
237
+ ...(artifact.metadata?.tags || [])
238
+ ].filter(Boolean).join(' ');
239
+ if (!searchTerms)
240
+ return [];
241
+ const related = await this.ucmClient.searchArtifacts({
242
+ category: artifact.metadata?.category,
243
+ subcategory: artifact.metadata?.subcategory,
244
+ limit: 5
245
+ });
246
+ // Filter out the current artifact and format results
247
+ return related
248
+ .filter(rel => rel.path !== artifact.path)
249
+ .slice(0, 3)
250
+ .map(rel => ({
251
+ name: rel.metadata?.name || 'Unknown',
252
+ path: rel.path,
253
+ category: rel.metadata?.category,
254
+ description: rel.metadata?.description?.substring(0, 100) + '...' || '',
255
+ similarity: this.calculateSimilarity(artifact, rel)
256
+ }));
257
+ }
258
+ catch (error) {
259
+ this.logger.debug('GetArtifactController', 'Could not fetch related artifacts', '', error);
260
+ return [];
261
+ }
262
+ }
263
+ detectContentType(artifact) {
264
+ const path = artifact.path || '';
265
+ const content = artifact.content || '';
266
+ if (path.includes('/typescript/') || content.includes('interface ') || content.includes('export class')) {
267
+ return 'typescript';
268
+ }
269
+ if (path.includes('/javascript/') || content.includes('function ') || content.includes('const ')) {
270
+ return 'javascript';
271
+ }
272
+ if (path.includes('/python/') || content.includes('def ') || content.includes('import ')) {
273
+ return 'python';
274
+ }
275
+ if (content.includes('```') || content.includes('# ')) {
276
+ return 'markdown';
277
+ }
278
+ return 'text';
279
+ }
280
+ detectLanguage(code) {
281
+ if (!code)
282
+ return 'text';
283
+ if (code.includes('interface ') || code.includes('export class'))
284
+ return 'typescript';
285
+ if (code.includes('function ') || code.includes('const '))
286
+ return 'javascript';
287
+ if (code.includes('def ') || code.includes('import '))
288
+ return 'python';
289
+ if (code.includes('<?php'))
290
+ return 'php';
291
+ if (code.includes('public class'))
292
+ return 'java';
293
+ return 'text';
294
+ }
295
+ getIncludedSections(options) {
296
+ const sections = [];
297
+ if (options.includeContent)
298
+ sections.push('content');
299
+ if (options.includeMetadata)
300
+ sections.push('metadata');
301
+ if (options.includeExamples)
302
+ sections.push('examples');
303
+ if (options.includeDependencies)
304
+ sections.push('dependencies');
305
+ if (options.includeVersionHistory)
306
+ sections.push('versionHistory');
307
+ return sections;
308
+ }
309
+ // Helper methods for metadata enrichment
310
+ isLatestVersion(_version) {
311
+ // In a real implementation, this would check against the latest version
312
+ return true; // Simplified
313
+ }
314
+ calculateQualityScore(metadata) {
315
+ let score = 50; // Base score
316
+ if (metadata.description && metadata.description.length > 20)
317
+ score += 20;
318
+ if (metadata.tags && metadata.tags.length > 0)
319
+ score += 10;
320
+ if (metadata.dependencies)
321
+ score += 10;
322
+ if (metadata.contractVersion)
323
+ score += 10;
324
+ return Math.min(score, 100);
325
+ }
326
+ estimateComplexity(metadata) {
327
+ const depCount = (metadata.dependencies?.services?.length || 0) +
328
+ (metadata.dependencies?.commands?.length || 0);
329
+ if (depCount === 0)
330
+ return 'simple';
331
+ if (depCount <= 3)
332
+ return 'moderate';
333
+ return 'complex';
334
+ }
335
+ assessMaturityLevel(metadata) {
336
+ const version = metadata.version || '0.0.0';
337
+ const [major] = version.split('.');
338
+ if (parseInt(major) >= 1)
339
+ return 'stable';
340
+ if (version.startsWith('0.'))
341
+ return 'beta';
342
+ return 'alpha';
343
+ }
344
+ sanitizeExternalDependencies(external) {
345
+ if (!external)
346
+ return {};
347
+ const sanitized = {};
348
+ for (const [key, value] of Object.entries(external)) {
349
+ // Remove potential secrets from configuration
350
+ if (typeof value === 'string' && (key.toLowerCase().includes('secret') || key.toLowerCase().includes('key'))) {
351
+ sanitized[key] = '[REDACTED]';
352
+ }
353
+ else {
354
+ sanitized[key] = value;
355
+ }
356
+ }
357
+ return sanitized;
358
+ }
359
+ // Simplified implementations for demo purposes
360
+ async checkDependencyResolution(_dependencies) {
361
+ return true; // Simplified
362
+ }
363
+ async findMissingDependencies(_dependencies) {
364
+ return []; // Simplified
365
+ }
366
+ async detectDependencyConflicts(_dependencies) {
367
+ return []; // Simplified
368
+ }
369
+ generateChangesSummary(_version) {
370
+ return 'Changes not tracked'; // Simplified
371
+ }
372
+ isBreakingChange(_version) {
373
+ return false; // Simplified
374
+ }
375
+ getDownloadCount(_artifact) {
376
+ return Math.floor(Math.random() * 1000); // Simulated
377
+ }
378
+ calculateRating(_artifact) {
379
+ return 3.0 + Math.random() * 2; // Simulated
380
+ }
381
+ getLastAccessTime() {
382
+ return new Date().toISOString();
383
+ }
384
+ calculateSimilarity(artifact1, artifact2) {
385
+ // Simple similarity calculation based on shared tags and category
386
+ let similarity = 0;
387
+ if (artifact1.metadata?.category === artifact2.metadata?.category) {
388
+ similarity += 0.4;
389
+ }
390
+ const tags1 = artifact1.metadata?.tags || [];
391
+ const tags2 = artifact2.metadata?.tags || [];
392
+ const sharedTags = tags1.filter((tag) => tags2.includes(tag));
393
+ similarity += (sharedTags.length / Math.max(tags1.length, tags2.length, 1)) * 0.6;
394
+ return Math.round(similarity * 100) / 100;
395
+ }
396
+ }
397
+ //# sourceMappingURL=GetArtifactController.js.map
@@ -0,0 +1,39 @@
1
+ import { BaseToolController } from '../base/BaseToolController.js';
2
+ import { UcmApiClient } from '../../clients/UcmApiClient.js';
3
+ import { ILogger } from '../../interfaces/ILogger.js';
4
+ export declare class GetLatestController extends BaseToolController {
5
+ constructor(ucmClient: UcmApiClient, logger: ILogger);
6
+ get name(): string;
7
+ get description(): string;
8
+ get inputSchema(): any;
9
+ protected handleExecute(params: any): Promise<any>;
10
+ private validateBasePath;
11
+ private getMostRecentVersion;
12
+ private buildLatestResponse;
13
+ private getVersionComparison;
14
+ private getChangeLog;
15
+ private compareVersions;
16
+ private detectContentType;
17
+ private calculateQualityScore;
18
+ private assessMaturityLevel;
19
+ private assessStability;
20
+ private determineReleaseType;
21
+ private determineLifecycleStage;
22
+ private determineSupportStatus;
23
+ private predictNextVersion;
24
+ private getDownloadCount;
25
+ private calculateRating;
26
+ private getRecentAccessCount;
27
+ private calculateTrendingScore;
28
+ private shouldRecommendUpgrade;
29
+ private requiresMigration;
30
+ private getDeprecationWarnings;
31
+ private getSecurityAlerts;
32
+ private calculateVersionJump;
33
+ private calculateTimespan;
34
+ private detectBreakingChanges;
35
+ private detectNewFeatures;
36
+ private detectImprovements;
37
+ private generateEstimatedChanges;
38
+ }
39
+ //# sourceMappingURL=GetLatestController.d.ts.map