@utaba/ucm-mcp-server 6.5.1 → 6.7.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/dist/clients/UcmLocalApiClient.d.ts +221 -2
- package/dist/clients/UcmLocalApiClient.js +211 -3
- package/dist/index.js +1 -1
- package/dist/interfaces/IMcpTool.d.ts +2 -2
- package/dist/server/ToolRegistry.js +44 -8
- package/dist/tools/authorization/ListAuthorizationsTool.js +2 -2
- package/dist/tools/authorization/SignOutTool.js +2 -2
- package/dist/tools/base/BaseToolController.d.ts +7 -4
- package/dist/tools/base/BaseToolController.js +28 -11
- package/dist/tools/connections/AccessConnectionTool.js +2 -2
- package/dist/tools/connections/CallRemoteToolTool.js +3 -3
- package/dist/tools/core/DeleteArtifactTool.js +5 -4
- package/dist/tools/core/EditArtifactMetadataTool.js +1 -1
- package/dist/tools/core/GetArtifactTool.js +1 -1
- package/dist/tools/core/GetArtifactVersionsTool.js +1 -1
- package/dist/tools/core/GetChunkTool.js +1 -1
- package/dist/tools/core/ListArtifactsTool.js +1 -1
- package/dist/tools/core/MoveArtifactTool.d.ts +1 -1
- package/dist/tools/core/MoveArtifactTool.js +2 -2
- package/dist/tools/core/PublishArtifactFromFileTool.js +1 -1
- package/dist/tools/core/PublishArtifactTool.js +2 -2
- package/dist/tools/core/SearchArtifactsTool.js +7 -6
- package/dist/tools/memory-graph/GraphCreateEntitiesTool.d.ts +14 -0
- package/dist/tools/memory-graph/GraphCreateEntitiesTool.js +58 -0
- package/dist/tools/memory-graph/GraphCreateRelationshipsTool.d.ts +14 -0
- package/dist/tools/memory-graph/GraphCreateRelationshipsTool.js +57 -0
- package/dist/tools/memory-graph/GraphCreateTool.d.ts +14 -0
- package/dist/tools/memory-graph/GraphCreateTool.js +64 -0
- package/dist/tools/memory-graph/GraphDeleteEntitiesTool.d.ts +14 -0
- package/dist/tools/memory-graph/GraphDeleteEntitiesTool.js +45 -0
- package/dist/tools/memory-graph/GraphDeleteRelationshipsTool.d.ts +14 -0
- package/dist/tools/memory-graph/GraphDeleteRelationshipsTool.js +45 -0
- package/dist/tools/memory-graph/GraphExploreTool.d.ts +14 -0
- package/dist/tools/memory-graph/GraphExploreTool.js +73 -0
- package/dist/tools/memory-graph/GraphFindEntitiesTool.d.ts +14 -0
- package/dist/tools/memory-graph/GraphFindEntitiesTool.js +68 -0
- package/dist/tools/memory-graph/GraphFindPathsTool.d.ts +14 -0
- package/dist/tools/memory-graph/GraphFindPathsTool.js +62 -0
- package/dist/tools/memory-graph/GraphGetEntityTool.d.ts +14 -0
- package/dist/tools/memory-graph/GraphGetEntityTool.js +49 -0
- package/dist/tools/memory-graph/GraphGetRelationshipsTool.d.ts +14 -0
- package/dist/tools/memory-graph/GraphGetRelationshipsTool.js +62 -0
- package/dist/tools/memory-graph/GraphListTemplatesTool.d.ts +14 -0
- package/dist/tools/memory-graph/GraphListTemplatesTool.js +34 -0
- package/dist/tools/memory-graph/GraphListTool.d.ts +14 -0
- package/dist/tools/memory-graph/GraphListTool.js +45 -0
- package/dist/tools/memory-graph/GraphOpenTool.d.ts +15 -0
- package/dist/tools/memory-graph/GraphOpenTool.js +50 -0
- package/dist/tools/memory-graph/GraphProposeVocabularyTool.d.ts +14 -0
- package/dist/tools/memory-graph/GraphProposeVocabularyTool.js +149 -0
- package/dist/tools/memory-graph/GraphSearchTool.d.ts +14 -0
- package/dist/tools/memory-graph/GraphSearchTool.js +94 -0
- package/dist/tools/memory-graph/GraphTraverseTool.d.ts +14 -0
- package/dist/tools/memory-graph/GraphTraverseTool.js +114 -0
- package/dist/tools/memory-graph/GraphUpdateEntitiesTool.d.ts +14 -0
- package/dist/tools/memory-graph/GraphUpdateEntitiesTool.js +58 -0
- package/dist/tools/memory-graph/GraphUpdateTool.d.ts +14 -0
- package/dist/tools/memory-graph/GraphUpdateTool.js +59 -0
- package/dist/tools/memory-graph/KnowledgeSetListTool.d.ts +14 -0
- package/dist/tools/memory-graph/KnowledgeSetListTool.js +25 -0
- package/dist/tools/memory-graph/KnowledgeSetOpenTool.d.ts +14 -0
- package/dist/tools/memory-graph/KnowledgeSetOpenTool.js +31 -0
- package/dist/tools/repository/CreateRepositoryTool.js +10 -9
- package/dist/tools/repository/GetRepositoryTool.js +15 -15
- package/dist/tools/repository/UpdateRepositoryTool.js +10 -9
- package/dist/tools/sharepoint/SharePointListConnectionsTool.js +1 -1
- package/dist/tools/sharepoint/SharePointListFoldersTool.js +1 -1
- package/dist/tools/utility/AuthorIndexTool.js +6 -5
- package/dist/tools/utility/AuthorRecentsTool.js +6 -5
- package/dist/tools/utility/ListRepositoriesTool.js +5 -4
- package/dist/utils/McpErrorHandler.js +1 -1
- package/package.json +1 -1
- package/package.json.backup +1 -1
- package/dist/clients/UcmApiClient.d.ts +0 -157
- package/dist/clients/UcmApiClient.js +0 -443
- package/dist/publish/package.json +0 -37
- package/dist/tools/artifacts/GetArtifactController.d.ts +0 -34
- package/dist/tools/artifacts/GetArtifactController.js +0 -397
- package/dist/tools/artifacts/GetLatestController.d.ts +0 -39
- package/dist/tools/artifacts/GetLatestController.js +0 -469
- package/dist/tools/artifacts/ListVersionsController.d.ts +0 -43
- package/dist/tools/artifacts/ListVersionsController.js +0 -530
- package/dist/tools/artifacts/PublishArtifactController.d.ts +0 -37
- package/dist/tools/artifacts/PublishArtifactController.js +0 -605
- package/dist/tools/discovery/BrowseCategoriesController.d.ts +0 -25
- package/dist/tools/discovery/BrowseCategoriesController.js +0 -400
- package/dist/tools/discovery/FindByPurposeController.d.ts +0 -12
- package/dist/tools/discovery/FindByPurposeController.js +0 -131
- package/dist/tools/discovery/ListAuthorsController.d.ts +0 -20
- package/dist/tools/discovery/ListAuthorsController.js +0 -274
- package/dist/tools/discovery/SearchArtifactsController.d.ts +0 -14
- package/dist/tools/discovery/SearchArtifactsController.js +0 -226
- package/dist/tools/navigation/ExploreNamespaceController.d.ts +0 -35
- package/dist/tools/navigation/ExploreNamespaceController.js +0 -548
- package/dist/tools/repository/DeleteRepositoryGuidanceTool.d.ts +0 -13
- package/dist/tools/repository/DeleteRepositoryGuidanceTool.js +0 -93
- package/dist/tools/sharepoint/SharePointSignOutTool.d.ts +0 -22
- package/dist/tools/sharepoint/SharePointSignOutTool.js +0 -114
- package/dist/tools/utility/HealthCheckController.d.ts +0 -11
- package/dist/tools/utility/HealthCheckController.js +0 -60
- package/dist/tools/utility/SubmitFeedbackTool.d.ts +0 -16
- package/dist/tools/utility/SubmitFeedbackTool.js +0 -68
- package/dist/tools/utility/ValidatePathController.d.ts +0 -30
- package/dist/tools/utility/ValidatePathController.js +0 -465
- package/dist/utils/HttpsAgentFactory.d.ts +0 -21
- package/dist/utils/HttpsAgentFactory.js +0 -50
- package/dist/utils/ValidationUtils.d.ts +0 -10
- package/dist/utils/ValidationUtils.js +0 -50
|
@@ -1,548 +0,0 @@
|
|
|
1
|
-
import { BaseToolController } from '../base/BaseToolController.js';
|
|
2
|
-
import { ValidationUtils } from '../../utils/ValidationUtils.js';
|
|
3
|
-
export class ExploreNamespaceController extends BaseToolController {
|
|
4
|
-
constructor(ucmClient, logger) {
|
|
5
|
-
super(ucmClient, logger);
|
|
6
|
-
}
|
|
7
|
-
get name() {
|
|
8
|
-
return 'mcp_ucm_explore_namespace';
|
|
9
|
-
}
|
|
10
|
-
get description() {
|
|
11
|
-
return 'Explore the hierarchical namespace structure of UCM artifacts with interactive navigation';
|
|
12
|
-
}
|
|
13
|
-
get inputSchema() {
|
|
14
|
-
return {
|
|
15
|
-
type: 'object',
|
|
16
|
-
properties: {
|
|
17
|
-
path: {
|
|
18
|
-
type: 'string',
|
|
19
|
-
description: 'Namespace path to explore (e.g., "utaba", "utaba/commands", "utaba/commands/user"). Leave empty for root exploration.',
|
|
20
|
-
default: '',
|
|
21
|
-
maxLength: 150
|
|
22
|
-
},
|
|
23
|
-
depth: {
|
|
24
|
-
type: 'number',
|
|
25
|
-
minimum: 1,
|
|
26
|
-
maximum: 5,
|
|
27
|
-
default: 2,
|
|
28
|
-
description: 'How deep to explore the namespace hierarchy'
|
|
29
|
-
},
|
|
30
|
-
includeContent: {
|
|
31
|
-
type: 'boolean',
|
|
32
|
-
default: false,
|
|
33
|
-
description: 'Include content previews for artifacts found'
|
|
34
|
-
},
|
|
35
|
-
includeStats: {
|
|
36
|
-
type: 'boolean',
|
|
37
|
-
default: true,
|
|
38
|
-
description: 'Include statistics for each namespace level'
|
|
39
|
-
},
|
|
40
|
-
sortBy: {
|
|
41
|
-
type: 'string',
|
|
42
|
-
enum: ['name', 'count', 'recent', 'popular'],
|
|
43
|
-
default: 'name',
|
|
44
|
-
description: 'Sort namespaces by specified criteria'
|
|
45
|
-
},
|
|
46
|
-
filterBy: {
|
|
47
|
-
type: 'object',
|
|
48
|
-
properties: {
|
|
49
|
-
technology: {
|
|
50
|
-
type: 'string',
|
|
51
|
-
description: 'Filter by technology (e.g., "typescript", "python")'
|
|
52
|
-
},
|
|
53
|
-
category: {
|
|
54
|
-
type: 'string',
|
|
55
|
-
enum: ['commands', 'services', 'patterns', 'implementations', 'contracts', 'guidance'],
|
|
56
|
-
description: 'Filter by artifact category'
|
|
57
|
-
},
|
|
58
|
-
hasArtifacts: {
|
|
59
|
-
type: 'boolean',
|
|
60
|
-
description: 'Only show namespaces that contain artifacts'
|
|
61
|
-
},
|
|
62
|
-
updatedSince: {
|
|
63
|
-
type: 'string',
|
|
64
|
-
format: 'date',
|
|
65
|
-
description: 'Only show namespaces with artifacts updated since this date'
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
},
|
|
69
|
-
expandPaths: {
|
|
70
|
-
type: 'array',
|
|
71
|
-
items: { type: 'string' },
|
|
72
|
-
description: 'Specific paths to expand regardless of depth limit'
|
|
73
|
-
},
|
|
74
|
-
includeNavigationHints: {
|
|
75
|
-
type: 'boolean',
|
|
76
|
-
default: true,
|
|
77
|
-
description: 'Include hints for further navigation'
|
|
78
|
-
}
|
|
79
|
-
},
|
|
80
|
-
required: []
|
|
81
|
-
};
|
|
82
|
-
}
|
|
83
|
-
async handleExecute(params) {
|
|
84
|
-
const { path = '', depth = 2, includeContent = false, includeStats = true, sortBy = 'name', filterBy = {}, expandPaths = [], includeNavigationHints = true } = params;
|
|
85
|
-
// Validate inputs
|
|
86
|
-
if (path && !this.isValidNamespacePath(path)) {
|
|
87
|
-
throw this.formatError(new Error('Invalid namespace path format'));
|
|
88
|
-
}
|
|
89
|
-
if (filterBy.category) {
|
|
90
|
-
ValidationUtils.validateCategory(filterBy.category);
|
|
91
|
-
}
|
|
92
|
-
this.logger.debug('ExploreNamespaceController', `Exploring namespace: "${path}" with depth ${depth}`);
|
|
93
|
-
try {
|
|
94
|
-
// Start exploration from the specified path
|
|
95
|
-
const explorationResult = await this.exploreNamespace(path, depth, { includeContent, includeStats, sortBy, filterBy, expandPaths });
|
|
96
|
-
// Build comprehensive response
|
|
97
|
-
const response = {
|
|
98
|
-
exploration: explorationResult,
|
|
99
|
-
currentPath: path,
|
|
100
|
-
explorationOptions: {
|
|
101
|
-
depth,
|
|
102
|
-
includeContent,
|
|
103
|
-
includeStats,
|
|
104
|
-
sortBy,
|
|
105
|
-
appliedFilters: filterBy
|
|
106
|
-
},
|
|
107
|
-
navigation: includeNavigationHints ? this.generateNavigationHints(explorationResult) : null,
|
|
108
|
-
breadcrumbs: this.buildBreadcrumbs(path),
|
|
109
|
-
metadata: {
|
|
110
|
-
timestamp: new Date().toISOString(),
|
|
111
|
-
totalNodesExplored: this.countTotalNodes(explorationResult),
|
|
112
|
-
maxDepthReached: this.calculateMaxDepth(explorationResult),
|
|
113
|
-
hasMoreContent: this.hasMoreContent(explorationResult, depth)
|
|
114
|
-
}
|
|
115
|
-
};
|
|
116
|
-
this.logger.info('ExploreNamespaceController', `Explored namespace with ${response.metadata.totalNodesExplored} nodes`);
|
|
117
|
-
return response;
|
|
118
|
-
}
|
|
119
|
-
catch (error) {
|
|
120
|
-
this.logger.error('ExploreNamespaceController', `Failed to explore namespace: ${path}`, '', error);
|
|
121
|
-
throw error;
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
async exploreNamespace(path, remainingDepth, options) {
|
|
125
|
-
if (remainingDepth <= 0 && !options.expandPaths.includes(path)) {
|
|
126
|
-
return null;
|
|
127
|
-
}
|
|
128
|
-
const node = {
|
|
129
|
-
path,
|
|
130
|
-
name: this.getNameFromPath(path),
|
|
131
|
-
type: this.determineNodeType(path),
|
|
132
|
-
level: this.calculateLevel(path),
|
|
133
|
-
children: [],
|
|
134
|
-
artifacts: []
|
|
135
|
-
};
|
|
136
|
-
try {
|
|
137
|
-
// Get direct content at this level
|
|
138
|
-
const directContent = await this.getDirectContent(path, options.filterBy);
|
|
139
|
-
// Process artifacts at this level
|
|
140
|
-
if (directContent.artifacts && directContent.artifacts.length > 0) {
|
|
141
|
-
node.artifacts = await this.processArtifacts(directContent.artifacts, options);
|
|
142
|
-
}
|
|
143
|
-
// Process child namespaces
|
|
144
|
-
if (directContent.children && directContent.children.length > 0) {
|
|
145
|
-
const childPromises = directContent.children.map(async (childPath) => {
|
|
146
|
-
const shouldExpand = remainingDepth > 1 || options.expandPaths.includes(childPath);
|
|
147
|
-
if (shouldExpand) {
|
|
148
|
-
return await this.exploreNamespace(childPath, remainingDepth - 1, options);
|
|
149
|
-
}
|
|
150
|
-
else {
|
|
151
|
-
// Return summary info for unexplored children
|
|
152
|
-
return {
|
|
153
|
-
path: childPath,
|
|
154
|
-
name: this.getNameFromPath(childPath),
|
|
155
|
-
type: this.determineNodeType(childPath),
|
|
156
|
-
level: this.calculateLevel(childPath),
|
|
157
|
-
summary: await this.getNodeSummary(childPath, options.filterBy),
|
|
158
|
-
children: null, // Indicates unexplored
|
|
159
|
-
artifacts: []
|
|
160
|
-
};
|
|
161
|
-
}
|
|
162
|
-
});
|
|
163
|
-
const childResults = await Promise.all(childPromises);
|
|
164
|
-
node.children = childResults.filter(child => child !== null);
|
|
165
|
-
}
|
|
166
|
-
// Add statistics if requested
|
|
167
|
-
if (options.includeStats) {
|
|
168
|
-
node.statistics = await this.calculateNodeStatistics(node, options.filterBy);
|
|
169
|
-
}
|
|
170
|
-
// Sort children based on sort criteria
|
|
171
|
-
if (node.children && node.children.length > 0) {
|
|
172
|
-
node.children = this.sortNodes(node.children, options.sortBy);
|
|
173
|
-
}
|
|
174
|
-
return node;
|
|
175
|
-
}
|
|
176
|
-
catch (error) {
|
|
177
|
-
this.logger.warn('ExploreNamespaceController', `Failed to explore path: ${path}`, '', error);
|
|
178
|
-
return {
|
|
179
|
-
path,
|
|
180
|
-
name: this.getNameFromPath(path),
|
|
181
|
-
type: 'error',
|
|
182
|
-
level: this.calculateLevel(path),
|
|
183
|
-
error: error instanceof Error ? error.message : String(error),
|
|
184
|
-
children: [],
|
|
185
|
-
artifacts: []
|
|
186
|
-
};
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
async getDirectContent(path, filterBy) {
|
|
190
|
-
const content = {
|
|
191
|
-
artifacts: [],
|
|
192
|
-
children: []
|
|
193
|
-
};
|
|
194
|
-
try {
|
|
195
|
-
if (!path) {
|
|
196
|
-
// Root level - get all authors
|
|
197
|
-
const authors = await this.ucmClient.getAuthors();
|
|
198
|
-
content.children = authors.map((author) => author.id);
|
|
199
|
-
}
|
|
200
|
-
else {
|
|
201
|
-
const pathParts = path.split('/');
|
|
202
|
-
if (pathParts.length === 1) {
|
|
203
|
-
// Author level - get categories
|
|
204
|
-
const authorData = await this.ucmClient.getAuthor(pathParts[0]);
|
|
205
|
-
if (Array.isArray(authorData)) {
|
|
206
|
-
// Extract unique categories
|
|
207
|
-
const categories = new Set();
|
|
208
|
-
authorData.forEach((artifact) => {
|
|
209
|
-
if (artifact.metadata?.category) {
|
|
210
|
-
categories.add(artifact.metadata.category);
|
|
211
|
-
}
|
|
212
|
-
});
|
|
213
|
-
content.children = Array.from(categories).map(cat => `${path}/${cat}`);
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
else if (pathParts.length === 2) {
|
|
217
|
-
// Category level - get subcategories and artifacts
|
|
218
|
-
const [author, category] = pathParts;
|
|
219
|
-
const authorData = await this.ucmClient.getAuthor(author);
|
|
220
|
-
if (Array.isArray(authorData)) {
|
|
221
|
-
const categoryArtifacts = authorData.filter((artifact) => artifact.metadata?.category === category);
|
|
222
|
-
// Filter artifacts
|
|
223
|
-
const filteredArtifacts = this.applyFilters(categoryArtifacts, filterBy);
|
|
224
|
-
content.artifacts = filteredArtifacts;
|
|
225
|
-
// Extract subcategories
|
|
226
|
-
const subcategories = new Set();
|
|
227
|
-
categoryArtifacts.forEach((artifact) => {
|
|
228
|
-
if (artifact.metadata?.subcategory) {
|
|
229
|
-
subcategories.add(artifact.metadata.subcategory);
|
|
230
|
-
}
|
|
231
|
-
});
|
|
232
|
-
content.children = Array.from(subcategories).map(sub => `${path}/${sub}`);
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
|
-
else {
|
|
236
|
-
// Deeper levels - get artifacts
|
|
237
|
-
const artifacts = await this.getArtifactsAtPath(path);
|
|
238
|
-
content.artifacts = this.applyFilters(artifacts, filterBy);
|
|
239
|
-
}
|
|
240
|
-
}
|
|
241
|
-
}
|
|
242
|
-
catch (error) {
|
|
243
|
-
// If we can't get content, return empty but don't fail
|
|
244
|
-
this.logger.debug('ExploreNamespaceController', `No content found at path: ${path}`, '', error);
|
|
245
|
-
}
|
|
246
|
-
return content;
|
|
247
|
-
}
|
|
248
|
-
async getArtifactsAtPath(path) {
|
|
249
|
-
try {
|
|
250
|
-
// Try to get artifacts at this specific path
|
|
251
|
-
const pathParts = path.split('/');
|
|
252
|
-
if (pathParts.length >= 3) {
|
|
253
|
-
const [author, category, subcategory] = pathParts;
|
|
254
|
-
const authorData = await this.ucmClient.getAuthor(author);
|
|
255
|
-
if (Array.isArray(authorData)) {
|
|
256
|
-
return authorData.filter((artifact) => artifact.metadata?.category === category &&
|
|
257
|
-
artifact.metadata?.subcategory === subcategory);
|
|
258
|
-
}
|
|
259
|
-
}
|
|
260
|
-
}
|
|
261
|
-
catch (error) {
|
|
262
|
-
this.logger.debug('ExploreNamespaceController', `No artifacts at path: ${path}`, '', error);
|
|
263
|
-
}
|
|
264
|
-
return [];
|
|
265
|
-
}
|
|
266
|
-
applyFilters(artifacts, filterBy) {
|
|
267
|
-
let filtered = artifacts;
|
|
268
|
-
if (filterBy.technology) {
|
|
269
|
-
filtered = filtered.filter(artifact => artifact.metadata?.technology === filterBy.technology);
|
|
270
|
-
}
|
|
271
|
-
if (filterBy.category) {
|
|
272
|
-
filtered = filtered.filter(artifact => artifact.metadata?.category === filterBy.category);
|
|
273
|
-
}
|
|
274
|
-
if (filterBy.updatedSince) {
|
|
275
|
-
const sinceDate = new Date(filterBy.updatedSince);
|
|
276
|
-
filtered = filtered.filter(artifact => {
|
|
277
|
-
const updated = new Date(artifact.lastUpdated || artifact.publishedAt || 0);
|
|
278
|
-
return updated > sinceDate;
|
|
279
|
-
});
|
|
280
|
-
}
|
|
281
|
-
return filtered;
|
|
282
|
-
}
|
|
283
|
-
async processArtifacts(artifacts, options) {
|
|
284
|
-
return artifacts.map(artifact => {
|
|
285
|
-
const processed = {
|
|
286
|
-
id: artifact.id,
|
|
287
|
-
name: artifact.metadata?.name || 'Unknown',
|
|
288
|
-
path: artifact.path,
|
|
289
|
-
version: artifact.metadata?.version || 'unknown',
|
|
290
|
-
technology: artifact.metadata?.technology || null,
|
|
291
|
-
description: artifact.metadata?.description || '',
|
|
292
|
-
lastUpdated: artifact.lastUpdated,
|
|
293
|
-
tags: artifact.metadata?.tags || []
|
|
294
|
-
};
|
|
295
|
-
// Include content preview if requested
|
|
296
|
-
if (options.includeContent && artifact.content) {
|
|
297
|
-
processed.contentPreview = this.generateContentPreview(artifact.content);
|
|
298
|
-
}
|
|
299
|
-
return processed;
|
|
300
|
-
});
|
|
301
|
-
}
|
|
302
|
-
async getNodeSummary(path, filterBy) {
|
|
303
|
-
try {
|
|
304
|
-
const content = await this.getDirectContent(path, filterBy);
|
|
305
|
-
return {
|
|
306
|
-
artifactCount: content.artifacts?.length || 0,
|
|
307
|
-
childCount: content.children?.length || 0,
|
|
308
|
-
hasContent: (content.artifacts?.length || 0) > 0 || (content.children?.length || 0) > 0,
|
|
309
|
-
lastActivity: this.getLastActivity(content.artifacts || [])
|
|
310
|
-
};
|
|
311
|
-
}
|
|
312
|
-
catch (error) {
|
|
313
|
-
return {
|
|
314
|
-
artifactCount: 0,
|
|
315
|
-
childCount: 0,
|
|
316
|
-
hasContent: false,
|
|
317
|
-
lastActivity: null,
|
|
318
|
-
error: error instanceof Error ? error.message : String(error)
|
|
319
|
-
};
|
|
320
|
-
}
|
|
321
|
-
}
|
|
322
|
-
async calculateNodeStatistics(node, filterBy) {
|
|
323
|
-
const stats = {
|
|
324
|
-
directArtifacts: node.artifacts?.length || 0,
|
|
325
|
-
totalArtifacts: 0,
|
|
326
|
-
totalChildren: node.children?.length || 0,
|
|
327
|
-
depth: node.level,
|
|
328
|
-
technologies: new Set(),
|
|
329
|
-
categories: new Set(),
|
|
330
|
-
authors: new Set(),
|
|
331
|
-
lastActivity: null,
|
|
332
|
-
popularityScore: 0
|
|
333
|
-
};
|
|
334
|
-
// Count total artifacts recursively
|
|
335
|
-
stats.totalArtifacts = this.countArtifactsRecursively(node);
|
|
336
|
-
// Collect technology and category information
|
|
337
|
-
this.collectMetadataRecursively(node, stats);
|
|
338
|
-
// Calculate last activity
|
|
339
|
-
stats.lastActivity = this.getLastActivityRecursively(node);
|
|
340
|
-
// Calculate popularity score
|
|
341
|
-
stats.popularityScore = this.calculatePopularityScore(node);
|
|
342
|
-
return {
|
|
343
|
-
...stats,
|
|
344
|
-
technologies: Array.from(stats.technologies),
|
|
345
|
-
categories: Array.from(stats.categories),
|
|
346
|
-
authors: Array.from(stats.authors)
|
|
347
|
-
};
|
|
348
|
-
}
|
|
349
|
-
sortNodes(nodes, sortBy) {
|
|
350
|
-
return nodes.sort((a, b) => {
|
|
351
|
-
switch (sortBy) {
|
|
352
|
-
case 'count':
|
|
353
|
-
const aCount = (a.statistics?.totalArtifacts || a.summary?.artifactCount || 0);
|
|
354
|
-
const bCount = (b.statistics?.totalArtifacts || b.summary?.artifactCount || 0);
|
|
355
|
-
return bCount - aCount;
|
|
356
|
-
case 'recent':
|
|
357
|
-
const aActivity = a.statistics?.lastActivity || a.summary?.lastActivity || '1970-01-01';
|
|
358
|
-
const bActivity = b.statistics?.lastActivity || b.summary?.lastActivity || '1970-01-01';
|
|
359
|
-
return new Date(bActivity).getTime() - new Date(aActivity).getTime();
|
|
360
|
-
case 'popular':
|
|
361
|
-
const aPopularity = a.statistics?.popularityScore || 0;
|
|
362
|
-
const bPopularity = b.statistics?.popularityScore || 0;
|
|
363
|
-
return bPopularity - aPopularity;
|
|
364
|
-
default: // 'name'
|
|
365
|
-
return a.name.localeCompare(b.name);
|
|
366
|
-
}
|
|
367
|
-
});
|
|
368
|
-
}
|
|
369
|
-
generateNavigationHints(explorationResult) {
|
|
370
|
-
const hints = {
|
|
371
|
-
nextSteps: [],
|
|
372
|
-
interestingPaths: [],
|
|
373
|
-
recommendations: [],
|
|
374
|
-
shortcuts: []
|
|
375
|
-
};
|
|
376
|
-
// Analyze exploration result to generate helpful hints
|
|
377
|
-
if (explorationResult.children && explorationResult.children.length > 0) {
|
|
378
|
-
const unexplored = explorationResult.children.filter((child) => child.children === null);
|
|
379
|
-
if (unexplored.length > 0) {
|
|
380
|
-
hints.nextSteps.push(`Explore ${unexplored.length} unexplored child namespaces`);
|
|
381
|
-
hints.shortcuts.push('Use higher depth parameter to explore deeper automatically');
|
|
382
|
-
}
|
|
383
|
-
}
|
|
384
|
-
// Find interesting paths based on artifact counts
|
|
385
|
-
this.findInterestingPaths(explorationResult, hints.interestingPaths);
|
|
386
|
-
// Generate recommendations based on content
|
|
387
|
-
if (explorationResult.statistics) {
|
|
388
|
-
const stats = explorationResult.statistics;
|
|
389
|
-
if (stats.totalArtifacts > 10) {
|
|
390
|
-
hints.recommendations.push('This namespace has rich content - consider using search tools for specific artifacts');
|
|
391
|
-
}
|
|
392
|
-
if (stats.technologies.length > 3) {
|
|
393
|
-
hints.recommendations.push('Multiple technologies available - filter by technology for focused exploration');
|
|
394
|
-
}
|
|
395
|
-
}
|
|
396
|
-
return hints;
|
|
397
|
-
}
|
|
398
|
-
buildBreadcrumbs(path) {
|
|
399
|
-
if (!path) {
|
|
400
|
-
return [{ name: 'Root', path: '', level: 0 }];
|
|
401
|
-
}
|
|
402
|
-
const parts = path.split('/');
|
|
403
|
-
const breadcrumbs = [{ name: 'Root', path: '', level: 0 }];
|
|
404
|
-
let currentPath = '';
|
|
405
|
-
parts.forEach((part, index) => {
|
|
406
|
-
currentPath = currentPath ? `${currentPath}/${part}` : part;
|
|
407
|
-
breadcrumbs.push({
|
|
408
|
-
name: part,
|
|
409
|
-
path: currentPath,
|
|
410
|
-
level: index + 1
|
|
411
|
-
});
|
|
412
|
-
});
|
|
413
|
-
return breadcrumbs;
|
|
414
|
-
}
|
|
415
|
-
// Helper methods
|
|
416
|
-
isValidNamespacePath(path) {
|
|
417
|
-
if (!path)
|
|
418
|
-
return true; // Empty path is valid (root)
|
|
419
|
-
return /^[a-zA-Z0-9\-_]+(\/[a-zA-Z0-9\-_]+)*$/.test(path);
|
|
420
|
-
}
|
|
421
|
-
getNameFromPath(path) {
|
|
422
|
-
if (!path)
|
|
423
|
-
return 'Root';
|
|
424
|
-
const parts = path.split('/');
|
|
425
|
-
return parts[parts.length - 1];
|
|
426
|
-
}
|
|
427
|
-
determineNodeType(path) {
|
|
428
|
-
if (!path)
|
|
429
|
-
return 'root';
|
|
430
|
-
const parts = path.split('/');
|
|
431
|
-
switch (parts.length) {
|
|
432
|
-
case 1: return 'author';
|
|
433
|
-
case 2: return 'category';
|
|
434
|
-
case 3: return 'subcategory';
|
|
435
|
-
case 4: return 'technology-or-version';
|
|
436
|
-
default: return 'artifact';
|
|
437
|
-
}
|
|
438
|
-
}
|
|
439
|
-
calculateLevel(path) {
|
|
440
|
-
return path ? path.split('/').length : 0;
|
|
441
|
-
}
|
|
442
|
-
generateContentPreview(content) {
|
|
443
|
-
const lines = content.split('\n');
|
|
444
|
-
const preview = lines.slice(0, 5).join('\n');
|
|
445
|
-
return preview.length > 200 ? preview.substring(0, 200) + '...' : preview;
|
|
446
|
-
}
|
|
447
|
-
getLastActivity(artifacts) {
|
|
448
|
-
if (!artifacts || artifacts.length === 0)
|
|
449
|
-
return null;
|
|
450
|
-
const dates = artifacts
|
|
451
|
-
.map(artifact => artifact.lastUpdated || artifact.publishedAt)
|
|
452
|
-
.filter(date => date)
|
|
453
|
-
.sort((a, b) => new Date(b).getTime() - new Date(a).getTime());
|
|
454
|
-
return dates.length > 0 ? dates[0] : null;
|
|
455
|
-
}
|
|
456
|
-
countTotalNodes(node) {
|
|
457
|
-
if (!node)
|
|
458
|
-
return 0;
|
|
459
|
-
let count = 1; // Count this node
|
|
460
|
-
if (node.children) {
|
|
461
|
-
count += node.children.reduce((sum, child) => sum + this.countTotalNodes(child), 0);
|
|
462
|
-
}
|
|
463
|
-
return count;
|
|
464
|
-
}
|
|
465
|
-
calculateMaxDepth(node) {
|
|
466
|
-
if (!node || !node.children || node.children.length === 0) {
|
|
467
|
-
return node ? node.level || 0 : 0;
|
|
468
|
-
}
|
|
469
|
-
return Math.max(...node.children.map((child) => this.calculateMaxDepth(child)));
|
|
470
|
-
}
|
|
471
|
-
hasMoreContent(node, requestedDepth) {
|
|
472
|
-
if (!node)
|
|
473
|
-
return false;
|
|
474
|
-
// Check if any children were not fully explored
|
|
475
|
-
if (node.children) {
|
|
476
|
-
return node.children.some((child) => child.children === null || this.hasMoreContent(child, requestedDepth));
|
|
477
|
-
}
|
|
478
|
-
return false;
|
|
479
|
-
}
|
|
480
|
-
countArtifactsRecursively(node) {
|
|
481
|
-
let count = node.artifacts?.length || 0;
|
|
482
|
-
if (node.children) {
|
|
483
|
-
count += node.children.reduce((sum, child) => sum + this.countArtifactsRecursively(child), 0);
|
|
484
|
-
}
|
|
485
|
-
return count;
|
|
486
|
-
}
|
|
487
|
-
collectMetadataRecursively(node, stats) {
|
|
488
|
-
// Collect from direct artifacts
|
|
489
|
-
if (node.artifacts) {
|
|
490
|
-
node.artifacts.forEach((artifact) => {
|
|
491
|
-
if (artifact.technology)
|
|
492
|
-
stats.technologies.add(artifact.technology);
|
|
493
|
-
if (artifact.metadata?.category)
|
|
494
|
-
stats.categories.add(artifact.metadata.category);
|
|
495
|
-
if (artifact.metadata?.author)
|
|
496
|
-
stats.authors.add(artifact.metadata.author);
|
|
497
|
-
});
|
|
498
|
-
}
|
|
499
|
-
// Collect from children
|
|
500
|
-
if (node.children) {
|
|
501
|
-
node.children.forEach((child) => this.collectMetadataRecursively(child, stats));
|
|
502
|
-
}
|
|
503
|
-
}
|
|
504
|
-
getLastActivityRecursively(node) {
|
|
505
|
-
const activities = [];
|
|
506
|
-
// Get activity from direct artifacts
|
|
507
|
-
const nodeActivity = this.getLastActivity(node.artifacts || []);
|
|
508
|
-
if (nodeActivity)
|
|
509
|
-
activities.push(nodeActivity);
|
|
510
|
-
// Get activity from children
|
|
511
|
-
if (node.children) {
|
|
512
|
-
node.children.forEach((child) => {
|
|
513
|
-
const childActivity = this.getLastActivityRecursively(child);
|
|
514
|
-
if (childActivity)
|
|
515
|
-
activities.push(childActivity);
|
|
516
|
-
});
|
|
517
|
-
}
|
|
518
|
-
if (activities.length === 0)
|
|
519
|
-
return null;
|
|
520
|
-
return activities.sort((a, b) => new Date(b).getTime() - new Date(a).getTime())[0];
|
|
521
|
-
}
|
|
522
|
-
calculatePopularityScore(node) {
|
|
523
|
-
// Simple popularity calculation based on artifact count and recency
|
|
524
|
-
const artifactCount = this.countArtifactsRecursively(node);
|
|
525
|
-
const lastActivity = this.getLastActivityRecursively(node);
|
|
526
|
-
let score = artifactCount * 10; // Base score from content
|
|
527
|
-
if (lastActivity) {
|
|
528
|
-
const daysSinceActivity = (Date.now() - new Date(lastActivity).getTime()) / (1000 * 60 * 60 * 24);
|
|
529
|
-
const recencyScore = Math.max(0, 100 - daysSinceActivity);
|
|
530
|
-
score += recencyScore;
|
|
531
|
-
}
|
|
532
|
-
return Math.round(score);
|
|
533
|
-
}
|
|
534
|
-
findInterestingPaths(node, interestingPaths) {
|
|
535
|
-
if (!node)
|
|
536
|
-
return;
|
|
537
|
-
const artifactCount = this.countArtifactsRecursively(node);
|
|
538
|
-
// Consider paths with significant content as interesting
|
|
539
|
-
if (artifactCount >= 5 && node.path) {
|
|
540
|
-
interestingPaths.push(`${node.path} (${artifactCount} artifacts)`);
|
|
541
|
-
}
|
|
542
|
-
// Recursively check children
|
|
543
|
-
if (node.children) {
|
|
544
|
-
node.children.forEach((child) => this.findInterestingPaths(child, interestingPaths));
|
|
545
|
-
}
|
|
546
|
-
}
|
|
547
|
-
}
|
|
548
|
-
//# sourceMappingURL=ExploreNamespaceController.js.map
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import { BaseToolController } from '../base/BaseToolController.js';
|
|
2
|
-
import { UcmLocalApiClient } from '../../clients/UcmLocalApiClient.js';
|
|
3
|
-
import { ILogger } from '../../interfaces/ILogger.js';
|
|
4
|
-
export declare class DeleteRepositoryGuidanceTool extends BaseToolController {
|
|
5
|
-
private baseUrl?;
|
|
6
|
-
constructor(ucmClient: UcmLocalApiClient, logger: ILogger, publishingAuthorId?: string, baseUrl?: string | undefined);
|
|
7
|
-
get name(): string;
|
|
8
|
-
get description(): string;
|
|
9
|
-
get inputSchema(): any;
|
|
10
|
-
protected validateParams(params: any): void;
|
|
11
|
-
protected handleExecute(params: any): Promise<any>;
|
|
12
|
-
}
|
|
13
|
-
//# sourceMappingURL=DeleteRepositoryGuidanceTool.d.ts.map
|
|
@@ -1,93 +0,0 @@
|
|
|
1
|
-
import { BaseToolController } from '../base/BaseToolController.js';
|
|
2
|
-
import { McpError, McpErrorCode } from '../../utils/McpErrorHandler.js';
|
|
3
|
-
export class DeleteRepositoryGuidanceTool extends BaseToolController {
|
|
4
|
-
baseUrl;
|
|
5
|
-
constructor(ucmClient, logger, publishingAuthorId, baseUrl) {
|
|
6
|
-
super(ucmClient, logger, publishingAuthorId);
|
|
7
|
-
this.baseUrl = baseUrl;
|
|
8
|
-
}
|
|
9
|
-
get name() {
|
|
10
|
-
return 'ucm_delete_repository_guidance';
|
|
11
|
-
}
|
|
12
|
-
get description() {
|
|
13
|
-
return `Provides guidance for deleting a repository via the web UI.`;
|
|
14
|
-
}
|
|
15
|
-
get inputSchema() {
|
|
16
|
-
return {
|
|
17
|
-
type: 'object',
|
|
18
|
-
properties: {
|
|
19
|
-
author: {
|
|
20
|
-
type: 'string',
|
|
21
|
-
description: this.publishingAuthorId ? `Workspace identifier: ${this.publishingAuthorId}` : 'Workspace identifier (e.g., "utaba", "1064600359")',
|
|
22
|
-
minLength: 1,
|
|
23
|
-
maxLength: 50
|
|
24
|
-
},
|
|
25
|
-
repository: {
|
|
26
|
-
type: 'string',
|
|
27
|
-
description: 'Repository name to delete (e.g., "main", "project-alpha")',
|
|
28
|
-
minLength: 1,
|
|
29
|
-
maxLength: 200
|
|
30
|
-
}
|
|
31
|
-
},
|
|
32
|
-
required: ['author', 'repository'],
|
|
33
|
-
additionalProperties: false
|
|
34
|
-
};
|
|
35
|
-
}
|
|
36
|
-
validateParams(params) {
|
|
37
|
-
super.validateParams(params);
|
|
38
|
-
if (!params.author || typeof params.author !== 'string' || params.author.trim() === '') {
|
|
39
|
-
throw new McpError(McpErrorCode.InvalidParams, 'Author identifier is required and cannot be empty');
|
|
40
|
-
}
|
|
41
|
-
if (!params.repository || typeof params.repository !== 'string' || params.repository.trim() === '') {
|
|
42
|
-
throw new McpError(McpErrorCode.InvalidParams, 'Repository name is required and cannot be empty');
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
async handleExecute(params) {
|
|
46
|
-
this.logger.info('DeleteRepositoryGuidanceTool', `Providing delete guidance for repository ${params.repository} for author ${params.author}`);
|
|
47
|
-
// Get the base URL for the web interface
|
|
48
|
-
const baseUrl = this.baseUrl;
|
|
49
|
-
const repositorySettingsUrl = `${baseUrl}/repository/${params.repository}/settings`;
|
|
50
|
-
const browseUrl = `${baseUrl}/browse/${params.author}`;
|
|
51
|
-
const guidance = {
|
|
52
|
-
action: 'delete_repository_guidance',
|
|
53
|
-
repository: {
|
|
54
|
-
author: params.author,
|
|
55
|
-
name: params.repository
|
|
56
|
-
},
|
|
57
|
-
message: `Repository deletion must be performed through the web interface for safety.`,
|
|
58
|
-
reason: 'Repository deletion is intentionally not available through MCP tools to prevent accidental deletion of valuable content.',
|
|
59
|
-
instructions: [
|
|
60
|
-
`1. Open the repository settings page: ${repositorySettingsUrl}`,
|
|
61
|
-
`2. Scroll to the "Danger Zone" section`,
|
|
62
|
-
`3. Click "Delete Repository" button`,
|
|
63
|
-
`4. Confirm the deletion by typing the repository name`,
|
|
64
|
-
`5. Click "Delete" to permanently remove the repository`
|
|
65
|
-
],
|
|
66
|
-
urls: {
|
|
67
|
-
repositorySettings: repositorySettingsUrl,
|
|
68
|
-
authorRepositories: browseUrl
|
|
69
|
-
},
|
|
70
|
-
warnings: [
|
|
71
|
-
'Repository deletion is permanent and cannot be undone',
|
|
72
|
-
'All artifacts and content in the repository will be permanently lost',
|
|
73
|
-
'Any links or references to this repository will become invalid',
|
|
74
|
-
'Make sure to backup any important content before deletion'
|
|
75
|
-
],
|
|
76
|
-
alternatives: [
|
|
77
|
-
'Consider renaming the repository instead of deleting it',
|
|
78
|
-
'Archive the repository by updating its description to indicate it is archived',
|
|
79
|
-
'Move important artifacts to another repository before deletion'
|
|
80
|
-
]
|
|
81
|
-
};
|
|
82
|
-
this.logger.info('DeleteRepositoryGuidanceTool', `Delete guidance provided for repository: ${params.repository}`);
|
|
83
|
-
return {
|
|
84
|
-
content: [
|
|
85
|
-
{
|
|
86
|
-
type: 'text',
|
|
87
|
-
text: JSON.stringify(guidance, null, 2)
|
|
88
|
-
}
|
|
89
|
-
]
|
|
90
|
-
};
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
//# sourceMappingURL=DeleteRepositoryGuidanceTool.js.map
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* SharePointSignOutTool
|
|
3
|
-
* Revoke user's OnBehalfOf authorization for a SharePoint connection
|
|
4
|
-
*/
|
|
5
|
-
import { BaseToolController } from '../base/BaseToolController.js';
|
|
6
|
-
import { UcmLocalApiClient } from '../../clients/UcmLocalApiClient.js';
|
|
7
|
-
import { ILogger } from '../../interfaces/ILogger.js';
|
|
8
|
-
export declare class SharePointSignOutTool extends BaseToolController {
|
|
9
|
-
constructor(ucmClient: UcmLocalApiClient, logger: ILogger, publishingAuthorId?: string);
|
|
10
|
-
get name(): string;
|
|
11
|
-
get description(): string;
|
|
12
|
-
get inputSchema(): any;
|
|
13
|
-
protected validateParams(params: any): void;
|
|
14
|
-
protected handleExecute(params: {
|
|
15
|
-
connectionId: string;
|
|
16
|
-
}): Promise<any>;
|
|
17
|
-
/**
|
|
18
|
-
* Format sign out response as markdown
|
|
19
|
-
*/
|
|
20
|
-
private formatSignOutResponse;
|
|
21
|
-
}
|
|
22
|
-
//# sourceMappingURL=SharePointSignOutTool.d.ts.map
|