imcp 0.1.1 → 0.1.3

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 (111) hide show
  1. package/dist/cli/index.js +1 -45
  2. package/dist/core/installers/clients/BaseClientInstaller.d.ts +1 -5
  3. package/dist/core/installers/clients/BaseClientInstaller.js +40 -38
  4. package/dist/core/installers/clients/ClientInstaller.d.ts +9 -9
  5. package/dist/core/installers/clients/ClientInstaller.js +105 -99
  6. package/dist/core/installers/requirements/BaseInstaller.d.ts +9 -1
  7. package/dist/core/installers/requirements/CommandInstaller.d.ts +9 -1
  8. package/dist/core/installers/requirements/CommandInstaller.js +46 -12
  9. package/dist/core/installers/requirements/GeneralInstaller.d.ts +11 -1
  10. package/dist/core/installers/requirements/GeneralInstaller.js +46 -10
  11. package/dist/core/installers/requirements/InstallerFactory.d.ts +3 -1
  12. package/dist/core/installers/requirements/InstallerFactory.js +3 -2
  13. package/dist/core/installers/requirements/NpmInstaller.d.ts +4 -2
  14. package/dist/core/installers/requirements/NpmInstaller.js +38 -22
  15. package/dist/core/installers/requirements/PipInstaller.d.ts +3 -1
  16. package/dist/core/installers/requirements/PipInstaller.js +58 -36
  17. package/dist/core/installers/requirements/RequirementInstaller.d.ts +4 -1
  18. package/dist/core/loaders/InstallOperationManager.d.ts +115 -0
  19. package/dist/core/loaders/InstallOperationManager.js +311 -0
  20. package/dist/core/loaders/SystemSettingsManager.d.ts +54 -0
  21. package/dist/core/loaders/SystemSettingsManager.js +257 -0
  22. package/dist/core/metadatas/recordingConstants.d.ts +44 -0
  23. package/dist/core/metadatas/recordingConstants.js +45 -0
  24. package/dist/core/metadatas/types.d.ts +21 -0
  25. package/dist/core/onboard/InstallOperationManager.d.ts +23 -0
  26. package/dist/core/onboard/InstallOperationManager.js +144 -0
  27. package/dist/core/onboard/OnboardStatusManager.js +2 -1
  28. package/dist/core/validators/StdioServerValidator.js +4 -3
  29. package/dist/services/InstallationService.d.ts +2 -37
  30. package/dist/services/InstallationService.js +45 -313
  31. package/dist/services/MCPManager.d.ts +1 -1
  32. package/dist/services/MCPManager.js +4 -58
  33. package/dist/services/RequirementService.d.ts +85 -12
  34. package/dist/services/RequirementService.js +488 -49
  35. package/dist/services/ServerService.d.ts +0 -6
  36. package/dist/services/ServerService.js +0 -74
  37. package/dist/utils/adoUtils.js +6 -3
  38. package/dist/utils/logger.js +1 -1
  39. package/dist/utils/macroExpressionUtils.js +3 -25
  40. package/dist/utils/osUtils.d.ts +22 -1
  41. package/dist/utils/osUtils.js +92 -1
  42. package/dist/utils/versionUtils.d.ts +20 -1
  43. package/dist/utils/versionUtils.js +51 -4
  44. package/dist/web/public/css/modal.css +292 -1
  45. package/dist/web/public/css/serverDetails.css +14 -1
  46. package/dist/web/public/index.html +122 -20
  47. package/dist/web/public/js/flights/flights.js +1 -0
  48. package/dist/web/public/js/modal/index.js +8 -14
  49. package/dist/web/public/js/modal/installModal.js +3 -4
  50. package/dist/web/public/js/modal/installation.js +122 -137
  51. package/dist/web/public/js/modal/loadingModal.js +155 -25
  52. package/dist/web/public/js/modal/messageQueue.js +45 -101
  53. package/dist/web/public/js/modal/modalSetup.js +125 -43
  54. package/dist/web/public/js/modal/modalUtils.js +0 -12
  55. package/dist/web/public/js/modal.js +23 -10
  56. package/dist/web/public/js/onboard/publishHandler.js +22 -20
  57. package/dist/web/public/js/serverCategoryDetails.js +60 -11
  58. package/dist/web/public/js/serverCategoryList.js +2 -2
  59. package/dist/web/public/js/settings.js +314 -0
  60. package/dist/web/public/settings.html +135 -0
  61. package/dist/web/public/styles.css +32 -0
  62. package/dist/web/server.js +82 -0
  63. package/memory-bank/activeContext.md +13 -1
  64. package/memory-bank/decisionLog.md +63 -0
  65. package/memory-bank/progress.md +30 -0
  66. package/memory-bank/systemPatterns.md +7 -0
  67. package/package.json +1 -1
  68. package/src/cli/index.ts +1 -48
  69. package/src/core/installers/clients/BaseClientInstaller.ts +64 -50
  70. package/src/core/installers/clients/ClientInstaller.ts +130 -130
  71. package/src/core/installers/requirements/BaseInstaller.ts +9 -1
  72. package/src/core/installers/requirements/CommandInstaller.ts +47 -13
  73. package/src/core/installers/requirements/GeneralInstaller.ts +48 -10
  74. package/src/core/installers/requirements/InstallerFactory.ts +4 -3
  75. package/src/core/installers/requirements/NpmInstaller.ts +90 -68
  76. package/src/core/installers/requirements/PipInstaller.ts +81 -55
  77. package/src/core/installers/requirements/RequirementInstaller.ts +4 -3
  78. package/src/core/loaders/InstallOperationManager.ts +367 -0
  79. package/src/core/loaders/SystemSettingsManager.ts +278 -0
  80. package/src/core/metadatas/recordingConstants.ts +62 -0
  81. package/src/core/metadatas/types.ts +23 -0
  82. package/src/core/onboard/OnboardStatusManager.ts +2 -1
  83. package/src/core/validators/StdioServerValidator.ts +4 -3
  84. package/src/services/InstallationService.ts +54 -399
  85. package/src/services/MCPManager.ts +4 -77
  86. package/src/services/RequirementService.ts +564 -67
  87. package/src/services/ServerService.ts +0 -90
  88. package/src/utils/adoUtils.ts +6 -4
  89. package/src/utils/logger.ts +1 -1
  90. package/src/utils/macroExpressionUtils.ts +4 -21
  91. package/src/utils/osUtils.ts +92 -1
  92. package/src/utils/versionUtils.ts +71 -19
  93. package/src/web/public/css/modal.css +292 -1
  94. package/src/web/public/css/serverDetails.css +14 -1
  95. package/src/web/public/index.html +122 -20
  96. package/src/web/public/js/flights/flights.js +1 -1
  97. package/src/web/public/js/modal/index.js +8 -14
  98. package/src/web/public/js/modal/installModal.js +3 -4
  99. package/src/web/public/js/modal/installation.js +122 -137
  100. package/src/web/public/js/modal/loadingModal.js +155 -25
  101. package/src/web/public/js/modal/modalSetup.js +125 -43
  102. package/src/web/public/js/modal/modalUtils.js +0 -12
  103. package/src/web/public/js/modal.js +23 -10
  104. package/src/web/public/js/onboard/publishHandler.js +22 -20
  105. package/src/web/public/js/serverCategoryDetails.js +60 -11
  106. package/src/web/public/js/serverCategoryList.js +5 -5
  107. package/src/web/public/js/settings.js +314 -0
  108. package/src/web/public/settings.html +135 -0
  109. package/src/web/public/styles.css +32 -0
  110. package/src/web/server.ts +85 -0
  111. package/src/web/public/js/modal/messageQueue.js +0 -112
@@ -1,350 +1,82 @@
1
- import path from 'path';
2
- import { fileURLToPath } from 'url';
3
- import { exec } from 'child_process';
4
- import util from 'util';
5
- import { createInstallerFactory } from '../core/installers/index.js';
6
- import { SUPPORTED_CLIENTS } from '../core/metadatas/constants.js';
7
1
  import { ClientInstaller } from '../core/installers/clients/ClientInstaller.js';
8
2
  import { ConfigurationProvider } from '../core/loaders/ConfigurationProvider.js';
9
3
  import { Logger } from '../utils/logger.js';
10
- const execPromise = util.promisify(exec);
11
- const __dirname = path.dirname(fileURLToPath(import.meta.url));
4
+ import { requirementService } from './RequirementService.js';
5
+ import { InstallOperationManager } from '../core/loaders/InstallOperationManager.js';
6
+ import * as RecordingConstants from '../core/metadatas/recordingConstants.js';
12
7
  /**
13
8
  * Handles the actual installation process for an MCP server.
14
9
  */
15
10
  export class InstallationService {
16
- activeInstallations = new Map();
17
- installerFactory;
18
11
  constructor() {
19
- this.installerFactory = createInstallerFactory();
20
- }
21
- generateOperationId() {
22
- return `install-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
12
+ // Constructor is now empty after removing installerFactory initialization
23
13
  }
24
14
  /**
25
- * Installs a server based on the provided options and feed configuration.
15
+ * Installs a server based on the provided options.
16
+ * @param categoryName The category name of the server.
26
17
  * @param serverName The name of the server to install.
27
18
  * @param options The installation options.
28
19
  * @returns A result object indicating success or failure.
29
20
  */
30
21
  async install(categoryName, serverName, options) {
22
+ // Reset any previous operation status for this server before starting a new one.
23
+ const recoder = await InstallOperationManager.getInstance(categoryName, serverName).resetOperation();
31
24
  const configProvider = ConfigurationProvider.getInstance();
32
- const clients = options.targetClients || Object.keys(SUPPORTED_CLIENTS);
25
+ const clients = options.targetClients || [];
33
26
  // Process updates for requirements if specified in options
34
- // Fire off requirement updates in the background without awaiting completion
35
27
  if (options.requirements && options.requirements.length > 0) {
36
- // Start the process but don't await it - it will run in the background
37
- this.processRequirementUpdates(categoryName, serverName, options)
38
- .catch(error => {
39
- console.error(`Error in background requirement updates: ${error instanceof Error ? error.message : String(error)}`);
28
+ recoder.recordingAsync(() => requirementService.processRequirementUpdates(categoryName, serverName, options), {
29
+ stepName: RecordingConstants.STEP_PROCESS_REQUIREMENT_UPDATES_SERVICE,
30
+ onError: (error) => {
31
+ const errorMsg = `Error in background requirement updates: ${error instanceof Error ? error.message : String(error)}`;
32
+ Logger.error(errorMsg);
33
+ return errorMsg;
34
+ },
35
+ onComplete: () => {
36
+ if (clients.length === 0)
37
+ recoder.markOverallStatus('completed', 'Requirement updates completed.');
38
+ }
40
39
  });
41
40
  }
42
- // Check if server is already ready
43
- const isReady = await configProvider.isServerReady(categoryName, serverName, clients);
41
+ if (!clients || clients.length === 0) {
42
+ const message = 'No clients specified for installation.';
43
+ return { success: true, message };
44
+ }
45
+ // Check if the server is already installed and ready
46
+ const readyMessage = 'Server and clients are already installed and ready';
47
+ const isReady = await recoder.recording(() => configProvider.isServerReady(categoryName, serverName, clients), {
48
+ stepName: RecordingConstants.STEP_CHECK_SERVER_READINESS,
49
+ inProgressMessage: 'Checking if server is already ready.',
50
+ endMessage: (ready) => ready ? 'Server and clients are already installed and ready' : 'Server is not ready. Proceeding with installation.',
51
+ });
44
52
  if (isReady) {
45
53
  return {
46
- success: true,
47
- message: 'Server and clients are already installed and ready',
54
+ success: true, message: readyMessage,
48
55
  status: [{
49
56
  status: 'completed',
50
57
  type: 'install',
51
58
  target: 'server',
52
- message: 'Server and clients are already installed and ready'
59
+ message: readyMessage,
53
60
  }]
54
61
  };
55
62
  }
56
63
  // Create new ClientInstaller instance for handling installation
57
64
  const clientInstaller = new ClientInstaller(categoryName, serverName, clients);
58
- const requirementsResult = await this.checkAndInstallRequirements(categoryName, serverName, options);
59
- if (requirementsResult) {
65
+ // Check and install requirements using RequirementService
66
+ const requirementsResult = await requirementService.checkAndInstallRequirements(categoryName, serverName, options);
67
+ // trigger a backend requirement check
68
+ await requirementService.checkServerRequirementForUpdateAsync(categoryName, serverName)
69
+ .then(() => {
70
+ Logger.info(`Requirement check for ${categoryName}:${serverName} completed successfully.`);
71
+ })
72
+ .catch((error) => {
73
+ Logger.error(`Requirement check for ${categoryName}:${serverName} failed: ${error instanceof Error ? error.message : String(error)}`);
74
+ });
75
+ if (requirementsResult && !requirementsResult.success) {
76
+ await recoder.recordStep('RequirementInstallationCheck', 'failed', requirementsResult.error?.message || requirementsResult.message || 'Requirement installation failed.');
60
77
  return requirementsResult;
61
78
  }
62
- // Process client installation regardless of requirements state
63
- // Each client installer will check requirements before actual installation
64
79
  return await clientInstaller.install(options);
65
80
  }
66
- /**
67
- * Process requirement updates specified in serverInstallOptions
68
- * All updates are processed in parallel for maximum efficiency
69
- * @param categoryName The category name
70
- * @param serverName The server name
71
- * @param requirements The requirements to update
72
- */
73
- async processRequirementUpdates(categoryName, serverName, options) {
74
- // Use UpdateCheckTracker to prevent concurrent updates
75
- const updateCheckTracker = await import('../utils/UpdateCheckTracker.js').then(m => m.updateCheckTracker);
76
- const operationKey = `requirement-updates-${categoryName}-${serverName}`;
77
- // Check if there's already an update operation in progress for this server
78
- const canProceed = await updateCheckTracker.startOperation(operationKey);
79
- if (!canProceed) {
80
- console.log(`Requirement updates for ${categoryName}/${serverName} already in progress, skipping`);
81
- return;
82
- }
83
- try {
84
- const configProvider = ConfigurationProvider.getInstance();
85
- const feedConfig = await configProvider.getFeedConfiguration(categoryName);
86
- if (!feedConfig) {
87
- console.error(`Feed configuration not found for category: ${categoryName}`);
88
- return;
89
- }
90
- // Import the RequirementService
91
- const { requirementService } = await import('./RequirementService.js');
92
- // Create an array of promises to update all requirements in parallel
93
- const updatePromises = options.requirements?.map(async (reqToUpdate) => {
94
- try {
95
- // Find the full requirement config
96
- const reqConfig = feedConfig.requirements?.find((r) => r.name === reqToUpdate.name);
97
- if (!reqConfig) {
98
- console.error(`Requirement configuration not found for: ${reqToUpdate.name}`);
99
- return;
100
- }
101
- // Get current status
102
- const currentStatus = await configProvider.getRequirementStatus(categoryName, reqToUpdate.name);
103
- if (!currentStatus) {
104
- console.error(`No current status found for requirement: ${reqToUpdate.name}`);
105
- return;
106
- }
107
- // Update requirement status to indicate update in progress
108
- await configProvider.updateRequirementStatus(categoryName, reqToUpdate.name, {
109
- ...currentStatus,
110
- name: reqToUpdate.name,
111
- type: currentStatus.type || 'unknown',
112
- installed: currentStatus.installed || false,
113
- inProgress: true,
114
- operationStatus: {
115
- status: 'in-progress',
116
- type: 'update',
117
- target: 'requirement',
118
- message: `Updating ${reqToUpdate.name} from ${currentStatus.version || 'unknown'} to ${reqToUpdate.version}`
119
- }
120
- });
121
- // For pip requirements, check if we have a stored pythonEnv
122
- if (reqConfig.type === 'pip' && currentStatus.pythonEnv && !options?.settings?.pythonEnv) {
123
- options = {
124
- ...options,
125
- settings: { ...options?.settings, pythonEnv: currentStatus.pythonEnv }
126
- };
127
- }
128
- // Update the requirement with options for pip environment
129
- const updatedStatus = await requirementService.updateRequirement(reqConfig, reqToUpdate.version, options);
130
- // Update requirement status
131
- await configProvider.updateRequirementStatus(categoryName, reqToUpdate.name, {
132
- ...updatedStatus,
133
- name: reqToUpdate.name,
134
- type: updatedStatus.type || currentStatus.type || 'unknown',
135
- installed: updatedStatus.installed,
136
- inProgress: false,
137
- operationStatus: {
138
- status: updatedStatus.installed ? 'completed' : 'failed',
139
- type: 'update',
140
- target: 'requirement',
141
- message: updatedStatus.installed
142
- ? `Successfully updated ${reqToUpdate.name} to version ${reqToUpdate.version}`
143
- : `Failed to update ${reqToUpdate.name} to version ${reqToUpdate.version}`
144
- },
145
- availableUpdate: updatedStatus.installed ? undefined : currentStatus.availableUpdate
146
- });
147
- console.log(`Requirement ${reqToUpdate.name} updated to version ${reqToUpdate.version}`);
148
- }
149
- catch (error) {
150
- console.error(`Error updating requirement ${reqToUpdate.name}:`, error);
151
- // Update status to indicate failure
152
- await configProvider.updateRequirementStatus(categoryName, reqToUpdate.name, {
153
- name: reqToUpdate.name,
154
- type: 'unknown',
155
- installed: false,
156
- inProgress: false,
157
- error: error instanceof Error ? error.message : String(error),
158
- operationStatus: {
159
- status: 'failed',
160
- type: 'update',
161
- target: 'requirement',
162
- message: `Error updating requirement: ${error instanceof Error ? error.message : String(error)}`
163
- }
164
- });
165
- }
166
- });
167
- // Wait for all updates to complete in parallel if there are any
168
- if (updatePromises) {
169
- await Promise.all(updatePromises);
170
- }
171
- }
172
- finally {
173
- // Always release the lock when done, even if there was an error
174
- await updateCheckTracker.endOperation(operationKey);
175
- }
176
- }
177
- /**
178
- * Checks and installs requirements for a server if needed
179
- * @param categoryName The category name
180
- * @param serverName The server name
181
- * @param options The installation options
182
- * @returns A failure result if requirements check fails, null if requirements are satisfied
183
- */
184
- async checkAndInstallRequirements(categoryName, serverName, options) {
185
- const configProvider = ConfigurationProvider.getInstance();
186
- // Get feed configuration to get requirements
187
- const feedConfig = await configProvider.getFeedConfiguration(categoryName);
188
- if (!feedConfig) {
189
- return {
190
- success: false,
191
- message: 'Feed configuration not found',
192
- status: [{
193
- status: 'failed',
194
- type: 'install',
195
- target: 'server',
196
- message: 'Feed configuration not found'
197
- }]
198
- };
199
- }
200
- // Find server config and verify requirements
201
- const serverConfig = feedConfig.mcpServers.find((s) => s.name === serverName);
202
- if (!serverConfig?.dependencies?.requirements) {
203
- Logger.debug(`No requirements for ${serverName}`);
204
- return null;
205
- }
206
- // Check all requirements installation status
207
- const requirementStatuses = await Promise.all(serverConfig.dependencies.requirements.map(async (req) => {
208
- const reqConfig = feedConfig.requirements?.find((r) => r.name === req.name) || {
209
- name: req.name,
210
- version: req.version,
211
- type: 'npm'
212
- };
213
- return await this.installerFactory.checkInstallation(reqConfig, options);
214
- }));
215
- // If all requirements are installed and ready, no need to proceed with installation
216
- if (requirementStatuses.every(status => status.installed)) {
217
- // Check if requirements are ready via ConfigurationProvider
218
- const requirementsReady = await configProvider.isRequirementsReady(categoryName, serverName);
219
- // Update requirement status if not ready
220
- if (!requirementsReady) {
221
- for (const status of requirementStatuses) {
222
- await configProvider.updateRequirementStatus(categoryName, status.name, status);
223
- }
224
- }
225
- return null;
226
- }
227
- // Sort requirements by order for installation
228
- const sortedRequirements = [...serverConfig.dependencies.requirements].sort((a, b) => {
229
- const orderA = a.order ?? Infinity;
230
- const orderB = b.order ?? Infinity;
231
- return orderA - orderB;
232
- });
233
- // Start requirements installation in background
234
- this.installRequirementsInBackground(categoryName, sortedRequirements, options)
235
- .catch(error => {
236
- Logger.error(`Error in background requirement installations: ${error instanceof Error ? error.message : String(error)}`);
237
- });
238
- // Return immediately while installation continues in background
239
- return null;
240
- }
241
- /**
242
- * Installs requirements in background without blocking the main thread
243
- * Requirements with the same order are installed in parallel
244
- */
245
- async installRequirementsInBackground(categoryName, sortedRequirements, options) {
246
- const configProvider = ConfigurationProvider.getInstance();
247
- const requirementGroups = sortedRequirements.reduce((groups, req) => {
248
- const order = req.order ?? Infinity;
249
- if (!groups[order]) {
250
- groups[order] = [];
251
- }
252
- groups[order].push(req);
253
- return groups;
254
- }, {});
255
- // Process each group in sequence, but requirements within group in parallel
256
- const orderKeys = Object.keys(requirementGroups).map(Number).sort((a, b) => a - b);
257
- for (const order of orderKeys) {
258
- const group = requirementGroups[order];
259
- await Promise.all(group.map(async (requirement) => {
260
- try {
261
- const feeds = await configProvider.getFeedConfiguration(categoryName);
262
- const requirementConfig = feeds?.requirements?.find((r) => r.name === requirement.name) || {
263
- name: requirement.name,
264
- version: requirement.version,
265
- type: 'npm'
266
- };
267
- // For pip requirements, check if we need to use stored pythonEnv
268
- const currentStatus = await configProvider.getRequirementStatus(categoryName, requirement.name);
269
- if (requirementConfig.type === 'pip' && currentStatus?.pythonEnv && !options?.settings?.pythonEnv) {
270
- options = {
271
- ...options,
272
- settings: { ...options?.settings, pythonEnv: currentStatus.pythonEnv }
273
- };
274
- }
275
- const installer = this.installerFactory.getInstaller(requirementConfig);
276
- if (!installer) {
277
- await this.updateRequirementFailureStatus(categoryName, requirement.name, requirementConfig.type, `No installer found for requirement type: ${requirementConfig.type}`);
278
- return;
279
- }
280
- const operationId = this.generateOperationId();
281
- await this.updateRequirementProgressStatus(categoryName, requirement.name, requirementConfig.type, operationId);
282
- const installStatus = await installer.install(requirementConfig, options);
283
- await this.updateRequirementCompletionStatus(categoryName, requirement.name, installStatus, operationId);
284
- }
285
- catch (error) {
286
- await this.updateRequirementFailureStatus(categoryName, requirement.name, 'unknown', error instanceof Error ? error.message : String(error));
287
- }
288
- }));
289
- }
290
- }
291
- /**
292
- * Helper to update requirement status for failure case
293
- */
294
- async updateRequirementFailureStatus(categoryName, requirementName, requirementType, errorMessage) {
295
- const configProvider = ConfigurationProvider.getInstance();
296
- await configProvider.updateRequirementStatus(categoryName, requirementName, {
297
- name: requirementName,
298
- type: requirementType,
299
- installed: false,
300
- error: errorMessage,
301
- operationStatus: {
302
- status: 'failed',
303
- type: 'install',
304
- target: 'requirement',
305
- message: `Error installing requirement: ${errorMessage}`,
306
- operationId: this.generateOperationId()
307
- }
308
- });
309
- }
310
- /**
311
- * Helper to update requirement status for in-progress case
312
- */
313
- async updateRequirementProgressStatus(categoryName, requirementName, requirementType, operationId) {
314
- const configProvider = ConfigurationProvider.getInstance();
315
- await configProvider.updateRequirementStatus(categoryName, requirementName, {
316
- name: requirementName,
317
- type: requirementType,
318
- installed: false,
319
- inProgress: true,
320
- operationStatus: {
321
- status: 'in-progress',
322
- type: 'install',
323
- target: 'requirement',
324
- message: `Installing requirement: ${requirementName}`,
325
- operationId
326
- }
327
- });
328
- }
329
- /**
330
- * Helper to update requirement status for completion case
331
- */
332
- async updateRequirementCompletionStatus(categoryName, requirementName, installStatus, operationId) {
333
- const configProvider = ConfigurationProvider.getInstance();
334
- await configProvider.updateRequirementStatus(categoryName, requirementName, {
335
- ...installStatus,
336
- operationStatus: {
337
- status: installStatus.installed ? 'completed' : 'failed',
338
- type: 'install',
339
- target: 'requirement',
340
- message: installStatus.installed
341
- ? `Requirement ${requirementName} installed successfully`
342
- : `Failed to install ${requirementName}`,
343
- operationId
344
- }
345
- });
346
- }
347
81
  }
348
- // Export a singleton instance (optional)
349
- // export const installationService = new InstallationService();
350
82
  //# sourceMappingURL=InstallationService.js.map
@@ -6,6 +6,7 @@ export declare class MCPManager extends EventEmitter {
6
6
  private configProvider;
7
7
  private feedOnboardService;
8
8
  private schemaProvider;
9
+ private requirementsService;
9
10
  constructor();
10
11
  syncFeeds(): Promise<void>;
11
12
  initialize(feedFile?: string, schemasDirectory?: string): Promise<void>;
@@ -14,7 +15,6 @@ export declare class MCPManager extends EventEmitter {
14
15
  getServerMcpConfig(categoryName: string, serverName: string): Promise<import("../core/metadatas/types.js").McpConfig | undefined>;
15
16
  installServer(categoryName: string, serverName: string, requestOptions?: ServerInstallOptions): Promise<ServerOperationResult>;
16
17
  uninstallServer(categoryName: string, serverName: string, options?: ServerUninstallOptions): Promise<ServerOperationResult>;
17
- updateRequirement(categoryName: string, serverName: string, requirementName: string, updateVersion: string): Promise<ServerOperationResult>;
18
18
  /**
19
19
  * Onboards a new feed configuration
20
20
  * @param config The feed configuration to onboard
@@ -6,17 +6,20 @@ import { MCPEvent, } from '../core/metadatas/types.js';
6
6
  import { OnboardingProcessStatus } from '../core/onboard/OnboardStatus.js';
7
7
  import { Logger, EventType, EventStatus } from '../utils/logger.js';
8
8
  import { FeedOnboardService } from '../core/onboard/FeedOnboardService.js';
9
+ import { RequirementService } from './RequirementService.js';
9
10
  export class MCPManager extends EventEmitter {
10
11
  installationService;
11
12
  configProvider;
12
13
  feedOnboardService;
13
14
  schemaProvider;
15
+ requirementsService;
14
16
  constructor() {
15
17
  super();
16
18
  this.configProvider = ConfigurationProvider.getInstance();
17
19
  this.schemaProvider = ServerSchemaProvider.getInstance();
18
20
  this.installationService = new InstallationService();
19
21
  this.feedOnboardService = new FeedOnboardService();
22
+ this.requirementsService = RequirementService.getInstance();
20
23
  }
21
24
  async syncFeeds() {
22
25
  await this.configProvider.syncFeeds();
@@ -25,6 +28,7 @@ export class MCPManager extends EventEmitter {
25
28
  try {
26
29
  await this.configProvider.initialize(feedFile);
27
30
  await this.schemaProvider.initialize(schemasDirectory);
31
+ await this.requirementsService.checkRequirementForUpdateAsync();
28
32
  }
29
33
  catch (error) {
30
34
  console.error("Error during MCPManager initialization:", error);
@@ -148,64 +152,6 @@ export class MCPManager extends EventEmitter {
148
152
  };
149
153
  }
150
154
  }
151
- async updateRequirement(categoryName, serverName, requirementName, updateVersion) {
152
- try {
153
- const { requirementService } = await import('./RequirementService.js');
154
- const serverCategory = await this.configProvider.getServerCategory(categoryName);
155
- if (!serverCategory) {
156
- return {
157
- success: false,
158
- message: `Server category ${categoryName} is not onboarded`,
159
- };
160
- }
161
- if (!serverCategory.feedConfiguration) {
162
- return {
163
- success: false,
164
- message: `Server category ${categoryName} has no feed configuration`,
165
- };
166
- }
167
- // Find the requirement
168
- const requirement = serverCategory.feedConfiguration.requirements.find(r => r.name === requirementName);
169
- if (!requirement) {
170
- return {
171
- success: false,
172
- message: `Requirement ${requirementName} not found in category ${categoryName}`,
173
- };
174
- }
175
- // Update the requirement using requirementService
176
- const updatedStatus = await requirementService.updateRequirement(requirement, updateVersion);
177
- // Update the status in configuration
178
- await this.configProvider.updateRequirementStatus(categoryName, requirementName, updatedStatus);
179
- Logger.trackEvent(EventType.REQUIREMENT_UPDATE, {
180
- status: EventStatus.SUCCESS,
181
- categoryName,
182
- serverName,
183
- requirementName,
184
- updateVersion
185
- });
186
- return {
187
- success: true,
188
- message: `Successfully updated ${requirementName} to version ${updateVersion}`,
189
- };
190
- }
191
- catch (error) {
192
- const errorMessage = `Failed to update ${requirementName}: ${error instanceof Error ? error.message : String(error)}`;
193
- console.error(`Error updating requirement ${requirementName}:`, error);
194
- Logger.trackEvent(EventType.REQUIREMENT_UPDATE, {
195
- status: EventStatus.FAILED,
196
- errorMessage,
197
- categoryName,
198
- serverName,
199
- requirementName,
200
- updateVersion
201
- });
202
- return {
203
- success: false,
204
- message: errorMessage,
205
- error: error instanceof Error ? error : new Error(String(error)),
206
- };
207
- }
208
- }
209
155
  /**
210
156
  * Onboards a new feed configuration
211
157
  * @param config The feed configuration to onboard
@@ -1,4 +1,4 @@
1
- import { RequirementConfig, RequirementStatus, ServerInstallOptions } from '../core/metadatas/types.js';
1
+ import { RequirementConfig, RequirementStatus, ServerInstallOptions, ServerOperationResult } from '../core/metadatas/types.js';
2
2
  /**
3
3
  * Service responsible for managing requirements installation and status
4
4
  */
@@ -11,30 +11,103 @@ export declare class RequirementService {
11
11
  * @returns The RequirementService instance
12
12
  */
13
13
  static getInstance(): RequirementService;
14
+ private generateOperationId;
15
+ /**
16
+ * Checks and installs requirements for a server if needed.
17
+ * @param categoryName The category name.
18
+ * @param serverName The server name.
19
+ * @param options The installation options.
20
+ * @returns A failure result if requirements check fails, null if requirements are satisfied or installation started in background.
21
+ */
22
+ checkAndInstallRequirements(categoryName: string, serverName: string, options: ServerInstallOptions): Promise<ServerOperationResult | null>;
23
+ /**
24
+ * Installs requirements in background without blocking the main thread.
25
+ * Requirements with the same order are installed in parallel.
26
+ * @param categoryName The category name.
27
+ * @param feedConfig The feed configuration.
28
+ * @param sortedRequirements Array of requirements sorted by order.
29
+ * @param options The installation options.
30
+ */
31
+ private installRequirementsInBackground;
32
+ /**
33
+ * Helper to update requirement status for failure case.
34
+ * @param categoryName The category name.
35
+ * @param requirementName The name of the requirement.
36
+ * @param requirementType The type of the requirement.
37
+ * @param errorMessage The error message.
38
+ */
39
+ private updateRequirementFailureStatus;
40
+ /**
41
+ * Helper to update requirement status for in-progress case.
42
+ * @param categoryName The category name.
43
+ * @param requirementName The name of the requirement.
44
+ * @param requirementType The type of the requirement.
45
+ * @param operationId The operation ID.
46
+ */
47
+ private updateRequirementProgressStatus;
48
+ /**
49
+ * Helper to update requirement status for completion case.
50
+ * @param categoryName The category name.
51
+ * @param requirementName The name of the requirement.
52
+ * @param installStatus The installation status.
53
+ * @param operationId The operation ID.
54
+ */
55
+ private updateRequirementCompletionStatus;
56
+ /**
57
+ * Validate a requirement configuration.
58
+ * @param requirement The requirement to validate.
59
+ * @throws Error if the requirement is invalid.
60
+ */
61
+ private validateRequirement;
62
+ /**
63
+ * Check for updates to requirements for all server categories
64
+ * This method is called periodically to check for updates
65
+ */
66
+ checkRequirementForUpdateAsync(): Promise<void>;
67
+ /**
68
+ * Check for updates to requirements for a specific server category
69
+ * @param categoryName The name of the server category
70
+ * @param serverName The name of the server (optional)
71
+ */
72
+ checkServerRequirementForUpdateAsync(categoryName: string, serverName: string): Promise<void>;
73
+ /**
74
+ * Check for updates to requirements for a server category
75
+ * @param serverCategory The server category to check
76
+ * @param serverName The name of the server (optional). When serverName is provided, check the requirement always
77
+ * @private
78
+ */
79
+ private checkRequirementsForUpdateInternal;
14
80
  /**
15
81
  * Check the installation status of a requirement
16
82
  * @param requirement The requirement to check
83
+ * @param options Optional installation options
17
84
  * @returns The installation status
18
85
  */
19
86
  checkRequirementStatus(requirement: RequirementConfig, options?: ServerInstallOptions): Promise<RequirementStatus>;
20
87
  /**
21
88
  * Check if updates are available for a requirement
22
89
  * @param requirement The requirement to check for updates
90
+ * @param currentStatus The current status of the requirement
91
+ * @param categoryName The category name
92
+ * @param serverName The server name (optional)
23
93
  * @returns Updated status with available updates information
24
94
  */
25
- checkRequirementForUpdates(requirement: RequirementConfig, currentStatus: RequirementStatus): Promise<RequirementStatus>;
95
+ checkRequirementForUpdates(requirement: RequirementConfig, currentStatus: RequirementStatus, categoryName: string, serverName?: string): Promise<RequirementStatus>;
26
96
  /**
27
- * Update a requirement to a new version
28
- * @param requirement The requirement configuration
29
- * @param updateVersion The version to update to
30
- * @returns The updated requirement status
97
+ * Process requirement updates specified in serverInstallOptions.
98
+ * All updates are processed in parallel for maximum efficiency.
99
+ * @param categoryName The category name.
100
+ * @param serverName The server name.
101
+ * @param options The installation options.
31
102
  */
32
- updateRequirement(requirement: RequirementConfig, updateVersion: string, options?: ServerInstallOptions): Promise<RequirementStatus>;
103
+ processRequirementUpdates(categoryName: string, serverName: string, options: ServerInstallOptions): Promise<void>;
33
104
  /**
34
- * Validate a requirement configuration
35
- * @param requirement The requirement to validate
36
- * @throws Error if the requirement is invalid
37
- */
38
- private validateRequirement;
105
+ * Update a requirement to a new version
106
+ * @param requirement The requirement configuration
107
+ * @param updateVersion The version to update to
108
+ * @param options Optional installation options
109
+ * @returns The updated requirement status
110
+ */
111
+ private updateRequirement;
39
112
  }
40
113
  export declare const requirementService: RequirementService;