imcp 0.1.4 → 0.1.5

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 (228) hide show
  1. package/README.md +21 -4
  2. package/dist/cli/commands/install.js.map +1 -0
  3. package/dist/cli/commands/list.js.map +1 -0
  4. package/dist/cli/commands/pull.js.map +1 -0
  5. package/dist/cli/commands/serve.js.map +1 -0
  6. package/dist/cli/commands/start.d.ts +2 -0
  7. package/dist/cli/commands/start.js +32 -0
  8. package/dist/cli/commands/start.js.map +1 -0
  9. package/dist/cli/commands/sync.d.ts +2 -0
  10. package/dist/cli/commands/sync.js +17 -0
  11. package/dist/cli/commands/sync.js.map +1 -0
  12. package/dist/cli/commands/uninstall.js.map +1 -0
  13. package/dist/cli/index.js +0 -0
  14. package/dist/cli/index.js.map +1 -0
  15. package/dist/core/ConfigurationLoader.d.ts +32 -0
  16. package/{src/core/loaders/ConfigurationLoader.ts → dist/core/ConfigurationLoader.js} +236 -298
  17. package/dist/core/ConfigurationLoader.js.map +1 -0
  18. package/dist/core/ConfigurationProvider.d.ts +35 -0
  19. package/{src/core/loaders/ConfigurationProvider.ts → dist/core/ConfigurationProvider.js} +375 -462
  20. package/dist/core/ConfigurationProvider.js.map +1 -0
  21. package/dist/core/InstallationService.d.ts +50 -0
  22. package/dist/core/InstallationService.js +350 -0
  23. package/dist/core/InstallationService.js.map +1 -0
  24. package/dist/core/MCPManager.d.ts +28 -0
  25. package/dist/core/MCPManager.js +188 -0
  26. package/dist/core/MCPManager.js.map +1 -0
  27. package/dist/core/RequirementService.d.ts +40 -0
  28. package/dist/core/RequirementService.js +110 -0
  29. package/dist/core/RequirementService.js.map +1 -0
  30. package/dist/core/ServerSchemaLoader.d.ts +11 -0
  31. package/dist/core/ServerSchemaLoader.js +43 -0
  32. package/dist/core/ServerSchemaLoader.js.map +1 -0
  33. package/dist/core/ServerSchemaProvider.d.ts +17 -0
  34. package/dist/core/ServerSchemaProvider.js +120 -0
  35. package/dist/core/ServerSchemaProvider.js.map +1 -0
  36. package/dist/core/constants.d.ts +47 -0
  37. package/dist/core/constants.js +94 -0
  38. package/dist/core/constants.js.map +1 -0
  39. package/dist/core/installers/BaseInstaller.d.ts +74 -0
  40. package/dist/core/installers/BaseInstaller.js +253 -0
  41. package/dist/core/installers/BaseInstaller.js.map +1 -0
  42. package/dist/core/installers/ClientInstaller.d.ts +23 -0
  43. package/dist/core/installers/ClientInstaller.js +564 -0
  44. package/dist/core/installers/ClientInstaller.js.map +1 -0
  45. package/dist/core/installers/CommandInstaller.d.ts +37 -0
  46. package/{src/core/installers/requirements/CommandInstaller.ts → dist/core/installers/CommandInstaller.js} +173 -231
  47. package/dist/core/installers/CommandInstaller.js.map +1 -0
  48. package/dist/core/installers/GeneralInstaller.d.ts +33 -0
  49. package/dist/core/installers/GeneralInstaller.js +85 -0
  50. package/dist/core/installers/GeneralInstaller.js.map +1 -0
  51. package/dist/core/installers/InstallerFactory.d.ts +54 -0
  52. package/{src/core/installers/requirements/InstallerFactory.ts → dist/core/installers/InstallerFactory.js} +97 -114
  53. package/dist/core/installers/InstallerFactory.js.map +1 -0
  54. package/dist/core/installers/NpmInstaller.d.ts +26 -0
  55. package/dist/core/installers/NpmInstaller.js +127 -0
  56. package/dist/core/installers/NpmInstaller.js.map +1 -0
  57. package/dist/core/installers/PipInstaller.d.ts +28 -0
  58. package/dist/core/installers/PipInstaller.js +127 -0
  59. package/dist/core/installers/PipInstaller.js.map +1 -0
  60. package/{src/core/installers/requirements/RequirementInstaller.ts → dist/core/installers/RequirementInstaller.d.ts} +33 -42
  61. package/dist/core/installers/RequirementInstaller.js +3 -0
  62. package/dist/core/installers/RequirementInstaller.js.map +1 -0
  63. package/dist/core/installers/clients/BaseClientInstaller.js.map +1 -0
  64. package/dist/core/installers/clients/ClientInstaller.js.map +1 -0
  65. package/dist/core/installers/clients/ClientInstallerFactory.js.map +1 -0
  66. package/dist/core/installers/clients/ClineInstaller.js.map +1 -0
  67. package/dist/core/installers/clients/ExtensionInstaller.js.map +1 -0
  68. package/dist/core/installers/clients/GithubCopilotInstaller.js.map +1 -0
  69. package/dist/core/installers/clients/MSRooCodeInstaller.js.map +1 -0
  70. package/dist/core/installers/index.js.map +1 -0
  71. package/dist/core/installers/requirements/BaseInstaller.js.map +1 -0
  72. package/dist/core/installers/requirements/CommandInstaller.js.map +1 -0
  73. package/dist/core/installers/requirements/GeneralInstaller.js.map +1 -0
  74. package/dist/core/installers/requirements/InstallerFactory.js.map +1 -0
  75. package/dist/core/installers/requirements/NpmInstaller.js.map +1 -0
  76. package/dist/core/installers/requirements/NugetInstaller.js.map +1 -0
  77. package/dist/core/installers/requirements/PipInstaller.js.map +1 -0
  78. package/dist/core/installers/requirements/RequirementInstaller.js.map +1 -0
  79. package/dist/core/loaders/ConfigurationLoader.js.map +1 -0
  80. package/dist/core/loaders/ConfigurationProvider.js.map +1 -0
  81. package/dist/core/loaders/InstallOperationManager.js.map +1 -0
  82. package/dist/core/loaders/ServerSchemaLoader.js.map +1 -0
  83. package/dist/core/loaders/ServerSchemaProvider.js.map +1 -0
  84. package/dist/core/loaders/SystemSettingsManager.js.map +1 -0
  85. package/dist/core/metadatas/constants.js.map +1 -0
  86. package/dist/core/metadatas/recordingConstants.js.map +1 -0
  87. package/dist/core/metadatas/types.js.map +1 -0
  88. package/dist/core/onboard/FeedOnboardService.js.map +1 -0
  89. package/dist/core/onboard/OnboardProcessor.js.map +1 -0
  90. package/dist/core/onboard/OnboardStatus.js.map +1 -0
  91. package/dist/core/onboard/OnboardStatusManager.js.map +1 -0
  92. package/dist/core/types.d.ts +166 -0
  93. package/dist/core/types.js +16 -0
  94. package/dist/core/types.js.map +1 -0
  95. package/dist/core/validators/FeedValidator.js.map +1 -0
  96. package/dist/core/validators/IServerValidator.js.map +1 -0
  97. package/dist/core/validators/SSEServerValidator.js.map +1 -0
  98. package/dist/core/validators/ServerValidatorFactory.js.map +1 -0
  99. package/dist/core/validators/StdioServerValidator.js.map +1 -0
  100. package/dist/index.js.map +1 -0
  101. package/dist/services/InstallRequestValidator.d.ts +21 -0
  102. package/dist/services/InstallRequestValidator.js +99 -0
  103. package/dist/services/InstallRequestValidator.js.map +1 -0
  104. package/dist/services/InstallationService.js.map +1 -0
  105. package/dist/services/MCPManager.js.map +1 -0
  106. package/dist/services/RequirementService.js.map +1 -0
  107. package/dist/services/ServerService.js.map +1 -0
  108. package/dist/services/TelemetryService.js.map +1 -0
  109. package/dist/utils/UpdateCheckTracker.js.map +1 -0
  110. package/dist/utils/adoUtils.js.map +1 -0
  111. package/dist/utils/clientUtils.js.map +1 -0
  112. package/dist/utils/feedUtils.js.map +1 -0
  113. package/dist/utils/githubAuth.js.map +1 -0
  114. package/dist/utils/githubUtils.js.map +1 -0
  115. package/dist/utils/logger.js.map +1 -0
  116. package/dist/utils/macroExpressionUtils.js.map +1 -0
  117. package/dist/utils/osUtils.js.map +1 -0
  118. package/dist/utils/versionUtils.js.map +1 -0
  119. package/dist/web/contract/serverContract.js.map +1 -0
  120. package/dist/web/public/index.html +1 -1
  121. package/dist/web/public/js/modal/installHandler.js +227 -0
  122. package/dist/web/public/js/modal/loadingUI.js +74 -0
  123. package/dist/web/public/js/modal/messageQueue.js +101 -45
  124. package/dist/web/public/js/modal/modalUI.js +214 -0
  125. package/{src/web/public/js/modal/versionUtils.js → dist/web/public/js/modal/version.js} +1 -1
  126. package/dist/web/public/onboard.html +4 -4
  127. package/dist/web/server.js.map +1 -0
  128. package/package.json +5 -1
  129. package/.github/ISSUE_TEMPLATE/JitAccess.yml +0 -28
  130. package/.github/acl/access.yml +0 -20
  131. package/.github/compliance/inventory.yml +0 -5
  132. package/.github/policies/jit.yml +0 -19
  133. package/.roo/rules-code/rules.md +0 -88
  134. package/dist/core/onboard/InstallOperationManager.d.ts +0 -23
  135. package/dist/core/onboard/InstallOperationManager.js +0 -144
  136. package/docs/ONBOARDING_PAGE_DESIGN.md +0 -260
  137. package/docs/Telemetry.md +0 -136
  138. package/memory-bank/activeContext.md +0 -26
  139. package/memory-bank/decisionLog.md +0 -91
  140. package/memory-bank/productContext.md +0 -41
  141. package/memory-bank/progress.md +0 -35
  142. package/memory-bank/systemPatterns.md +0 -10
  143. package/src/cli/commands/install.ts +0 -139
  144. package/src/cli/commands/list.ts +0 -113
  145. package/src/cli/commands/pull.ts +0 -16
  146. package/src/cli/commands/serve.ts +0 -39
  147. package/src/cli/commands/uninstall.ts +0 -64
  148. package/src/cli/index.ts +0 -82
  149. package/src/core/installers/clients/BaseClientInstaller.ts +0 -341
  150. package/src/core/installers/clients/ClientInstaller.ts +0 -222
  151. package/src/core/installers/clients/ClientInstallerFactory.ts +0 -43
  152. package/src/core/installers/clients/ClineInstaller.ts +0 -35
  153. package/src/core/installers/clients/ExtensionInstaller.ts +0 -165
  154. package/src/core/installers/clients/GithubCopilotInstaller.ts +0 -79
  155. package/src/core/installers/clients/MSRooCodeInstaller.ts +0 -32
  156. package/src/core/installers/index.ts +0 -11
  157. package/src/core/installers/requirements/BaseInstaller.ts +0 -85
  158. package/src/core/installers/requirements/GeneralInstaller.ts +0 -133
  159. package/src/core/installers/requirements/NpmInstaller.ts +0 -271
  160. package/src/core/installers/requirements/NugetInstaller.ts +0 -203
  161. package/src/core/installers/requirements/PipInstaller.ts +0 -207
  162. package/src/core/loaders/InstallOperationManager.ts +0 -367
  163. package/src/core/loaders/ServerSchemaLoader.ts +0 -117
  164. package/src/core/loaders/ServerSchemaProvider.ts +0 -99
  165. package/src/core/loaders/SystemSettingsManager.ts +0 -278
  166. package/src/core/metadatas/constants.ts +0 -122
  167. package/src/core/metadatas/recordingConstants.ts +0 -65
  168. package/src/core/metadatas/types.ts +0 -202
  169. package/src/core/onboard/FeedOnboardService.ts +0 -501
  170. package/src/core/onboard/OnboardProcessor.ts +0 -356
  171. package/src/core/onboard/OnboardStatus.ts +0 -60
  172. package/src/core/onboard/OnboardStatusManager.ts +0 -416
  173. package/src/core/validators/FeedValidator.ts +0 -135
  174. package/src/core/validators/IServerValidator.ts +0 -21
  175. package/src/core/validators/SSEServerValidator.ts +0 -43
  176. package/src/core/validators/ServerValidatorFactory.ts +0 -51
  177. package/src/core/validators/StdioServerValidator.ts +0 -313
  178. package/src/index.ts +0 -44
  179. package/src/services/InstallationService.ts +0 -102
  180. package/src/services/MCPManager.ts +0 -249
  181. package/src/services/RequirementService.ts +0 -627
  182. package/src/services/ServerService.ts +0 -161
  183. package/src/services/TelemetryService.ts +0 -59
  184. package/src/utils/UpdateCheckTracker.ts +0 -86
  185. package/src/utils/adoUtils.ts +0 -293
  186. package/src/utils/clientUtils.ts +0 -72
  187. package/src/utils/feedUtils.ts +0 -31
  188. package/src/utils/githubAuth.ts +0 -212
  189. package/src/utils/githubUtils.ts +0 -164
  190. package/src/utils/logger.ts +0 -195
  191. package/src/utils/macroExpressionUtils.ts +0 -104
  192. package/src/utils/osUtils.ts +0 -700
  193. package/src/utils/versionUtils.ts +0 -114
  194. package/src/web/contract/serverContract.ts +0 -74
  195. package/src/web/public/css/detailsWidget.css +0 -235
  196. package/src/web/public/css/modal.css +0 -757
  197. package/src/web/public/css/notifications.css +0 -101
  198. package/src/web/public/css/onboard.css +0 -107
  199. package/src/web/public/css/serverCategoryList.css +0 -120
  200. package/src/web/public/css/serverDetails.css +0 -139
  201. package/src/web/public/index.html +0 -359
  202. package/src/web/public/js/api.js +0 -132
  203. package/src/web/public/js/detailsWidget.js +0 -264
  204. package/src/web/public/js/flights/flights.js +0 -127
  205. package/src/web/public/js/modal/index.js +0 -52
  206. package/src/web/public/js/modal/installModal.js +0 -162
  207. package/src/web/public/js/modal/installation.js +0 -266
  208. package/src/web/public/js/modal/loadingModal.js +0 -182
  209. package/src/web/public/js/modal/modalSetup.js +0 -595
  210. package/src/web/public/js/modal/modalUtils.js +0 -37
  211. package/src/web/public/js/modal.js +0 -42
  212. package/src/web/public/js/notifications.js +0 -137
  213. package/src/web/public/js/onboard/formProcessor.js +0 -1037
  214. package/src/web/public/js/onboard/index.js +0 -374
  215. package/src/web/public/js/onboard/publishHandler.js +0 -172
  216. package/src/web/public/js/onboard/state.js +0 -76
  217. package/src/web/public/js/onboard/templates.js +0 -342
  218. package/src/web/public/js/onboard/uiHandlers.js +0 -1076
  219. package/src/web/public/js/onboard/validationHandlers.js +0 -493
  220. package/src/web/public/js/serverCategoryDetails.js +0 -364
  221. package/src/web/public/js/serverCategoryList.js +0 -241
  222. package/src/web/public/js/settings.js +0 -314
  223. package/src/web/public/modal.html +0 -84
  224. package/src/web/public/onboard.html +0 -296
  225. package/src/web/public/settings.html +0 -135
  226. package/src/web/public/styles.css +0 -277
  227. package/src/web/server.ts +0 -478
  228. package/tsconfig.json +0 -18
@@ -1,341 +0,0 @@
1
- import { Logger } from '../../../utils/logger.js';
2
- import { exec } from 'child_process';
3
- import { promisify } from 'util';
4
- import { isCommandAvailable, getNpmExecutablePath } from '../../../utils/osUtils.js';
5
- import { ExtensionInstaller } from './ExtensionInstaller.js';
6
- import { SUPPORTED_CLIENTS } from '../../metadatas/constants.js';
7
- import {
8
- OperationStatus,
9
- McpConfig,
10
- ServerInstallOptions,
11
- } from '../../metadatas/types.js';
12
- import {
13
- MACRO_EXPRESSIONS,
14
- MacroResolverFunctions
15
- } from '../../../utils/macroExpressionUtils.js';
16
- import { InstallOperationManager } from '../../loaders/InstallOperationManager.js';
17
- import * as RecordingConstants from '../../metadatas/recordingConstants.js';
18
-
19
- const execAsync = promisify(exec);
20
-
21
- /**
22
- * Base class for client installers with shared functionality
23
- */
24
- export abstract class BaseClientInstaller {
25
- protected abstract readonly clientName: string;
26
- /**
27
- * Generate a unique operation ID for tracking installations
28
- */
29
- protected generateOperationId(): string {
30
- return `install-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
31
- }
32
-
33
- /**
34
- * Set up installation configuration with environment variables and arguments
35
- * Handles Python environment configuration if specified
36
- */
37
- protected async setupInstallConfig(
38
- serverConfig: McpConfig,
39
- options: ServerInstallOptions
40
- ): Promise<any> {
41
- const finalConfig: any = { ...serverConfig.installation };
42
- finalConfig.mode = serverConfig.mode;
43
-
44
- // Handle command line arguments
45
- if (options.args && options.args.length > 0) {
46
- Logger.debug(`Using args from ServerInstallOptions: ${options.args.join(' ')}`);
47
- finalConfig.args = options.args;
48
- }
49
-
50
- // Handle environment variables
51
- const baseEnv = finalConfig.env || {};
52
- const defaultEnv: Record<string, string> = {};
53
- for (const [key, config] of Object.entries(baseEnv)) {
54
- const envConfig = config as any;
55
- if (envConfig.Default) {
56
- defaultEnv[key] = envConfig.Default;
57
- }
58
- }
59
- finalConfig.env = { ...defaultEnv, ...(options.env || {}) };
60
-
61
- // Handle macro expressions
62
- await this._resolveConfigMacros(finalConfig, options);
63
-
64
- Logger.debug(`Final installation config: ${JSON.stringify(finalConfig)}`);
65
- return finalConfig;
66
- }
67
-
68
- /**
69
- * Resolves and replaces known macro expressions (e.g., ${PYTHON_PACKAGE}, ${NPMPATH}, ${BROWSER_PATH})
70
- * in the provided configuration object's 'args' and 'env' properties.
71
- * This method directly mutates the finalConfig object.
72
- * @param finalConfig The configuration object to modify.
73
- * @param options Server installation options which may contain settings like pythonEnv or npmPath.
74
- */
75
- private async _resolveConfigMacros(
76
- finalConfig: any,
77
- options: ServerInstallOptions
78
- ): Promise<void> {
79
- for (const macro of Object.values(MACRO_EXPRESSIONS)) {
80
- const isMacroInArgs = finalConfig.args?.some((arg: string) => typeof arg === 'string' && arg.includes(macro));
81
- const isMacroInEnv = Object.values(finalConfig.env || {}).some(value => typeof value === 'string' && value.includes(macro));
82
-
83
- if (!isMacroInArgs && !isMacroInEnv) {
84
- Logger.debug(`Macro ${macro} not found in args or env, skipping resolution.`);
85
- continue;
86
- }
87
-
88
- const resolver = MacroResolverFunctions[macro];
89
- if (resolver) {
90
- const resolvedValue = await resolver(finalConfig, options);
91
- if (resolvedValue !== undefined) {
92
- // Replace in args
93
- if (finalConfig.args) {
94
- const originalArgsString = finalConfig.args.join(' ');
95
- finalConfig.args = finalConfig.args.map((arg: string) =>
96
- typeof arg === 'string' && arg.includes(macro)
97
- ? arg.replace(new RegExp(macro.replace(/[${}]/g, '\\$&'), 'g'), resolvedValue)
98
- : arg
99
- );
100
- if (finalConfig.args.join(' ') !== originalArgsString) {
101
- Logger.debug(`Args after ${macro} ('${resolvedValue}') replacement: ${finalConfig.args.join(' ')}`);
102
- }
103
- }
104
- // Replace in env
105
- if (finalConfig.env) {
106
- const originalEnvJson = JSON.stringify(finalConfig.env);
107
- for (const key in finalConfig.env) {
108
- if (typeof finalConfig.env[key] === 'string' && (finalConfig.env[key] as string).includes(macro)) {
109
- finalConfig.env[key] = (finalConfig.env[key] as string).replace(new RegExp(macro.replace(/[${}]/g, '\\$&'), 'g'), resolvedValue);
110
- }
111
- }
112
- if (JSON.stringify(finalConfig.env) !== originalEnvJson) {
113
- Logger.debug(`Env after ${macro} ('${resolvedValue}') replacement: ${JSON.stringify(finalConfig.env)}`);
114
- }
115
- }
116
- } else {
117
- Logger.debug(`Could not resolve value for macro: ${macro}. It will not be replaced.`);
118
- }
119
- }
120
- }
121
- }
122
-
123
- /**
124
- * Handle NPX commands for Windows platform
125
- */
126
- protected async handleWindowsNpx(config: any): Promise<any> {
127
- if (process.platform === 'win32' && config.command === 'npx') {
128
- const npmPath = await getNpmExecutablePath();
129
- return {
130
- ...config,
131
- command: 'cmd',
132
- args: ['/c', 'npx', ...config.args],
133
- env: {
134
- ...config.env,
135
- 'APPDATA': npmPath
136
- }
137
- };
138
- }
139
- return config;
140
- }
141
-
142
- /**
143
- * Initialize settings object with client-specific structure
144
- * Override in child classes to provide custom initialization
145
- */
146
- protected initializeSettings(settings: any): void {
147
- if (!settings.mcpServers) {
148
- settings.mcpServers = {};
149
- }
150
- }
151
-
152
- /**
153
- * Handle stdio mode configuration
154
- * Override in child classes to provide custom stdio configuration
155
- */
156
- protected async handleStdioMode(settings: any, serverName: string, finalConfig: any): Promise<void> {
157
- // Convert backslashes to forward slashes in args
158
- if (finalConfig.args) {
159
- finalConfig.args = finalConfig.args.map((arg: string) =>
160
- typeof arg === 'string' ? arg.replace(/\\/g, '/') : arg
161
- );
162
- }
163
- settings.mcpServers[serverName] = {
164
- command: finalConfig.command,
165
- args: finalConfig.args,
166
- env: finalConfig.env,
167
- autoApprove: [],
168
- disabled: false,
169
- alwaysAllow: []
170
- };
171
- }
172
-
173
- /**
174
- * Handle SSE mode configuration
175
- * Override in child classes to provide custom SSE configuration
176
- */
177
- protected handleSseMode(settings: any, serverName: string, installConfig: any): void {
178
- settings.mcpServers[serverName] = {
179
- type: 'sse',
180
- url: installConfig.url
181
- };
182
- }
183
-
184
- /**
185
- * Checks if VS Code or VS Code Insiders is installed and installs the client extension.
186
- * @param operationId The operation ID for tracking.
187
- * @returns An OperationStatus object if checks fail or installation fails, otherwise undefined.
188
- */
189
- protected async checkVSCodeAndInstallExtension(operationId: string): Promise<OperationStatus | undefined> {
190
- // Check if VS Code or VS Code Insiders is installed
191
- const isVSCodeInstalled = await isCommandAvailable('code');
192
- const isVSCodeInsidersInstalled = await isCommandAvailable('code-insiders');
193
-
194
- if (!isVSCodeInstalled && !isVSCodeInsidersInstalled) {
195
- return {
196
- status: 'failed',
197
- type: 'install',
198
- target: 'server',
199
- message: 'Failed to install as neither VS Code nor VS Code Insiders are installed on this system. Please run `code` or `code-insiders` to make sure they are installed. Relaunch imcp after installation.',
200
- operationId
201
- };
202
- }
203
-
204
- // Install extension
205
- const extensionResult = await ExtensionInstaller.installExtension(this.clientName);
206
- if (!extensionResult) {
207
- Logger.debug(`Failed to install ${this.clientName} extension`);
208
- return {
209
- status: 'failed',
210
- type: 'install',
211
- target: 'server',
212
- message: `Failed to install ${this.clientName} extension`,
213
- operationId
214
- };
215
- }
216
- return undefined;
217
- }
218
-
219
- /**
220
- * Update VS Code settings for both VS Code and VS Code Insiders if installed
221
- * @param serverName The name of the server to configure
222
- * @param installConfig The installation configuration
223
- * @returns Array of results indicating success/failure for each VS Code variant
224
- */
225
- protected async updateVSCodeSettings(serverName: string, installConfig: any): Promise<Array<{ success: boolean; path: string; error?: string }>> {
226
- const results: Array<{ success: boolean; path: string; error?: string }> = [];
227
- const isVSCodeInstalled = await isCommandAvailable('code');
228
- const isVSCodeInsidersInstalled = await isCommandAvailable('code-insiders');
229
-
230
- // Update settings for VS Code if installed
231
- if (isVSCodeInstalled) {
232
- try {
233
- const settingPath = SUPPORTED_CLIENTS[this.clientName].codeSettingPath;
234
- await this.setupClientSettings(settingPath, serverName, installConfig);
235
- results.push({ success: true, path: settingPath });
236
- } catch (error) {
237
- results.push({
238
- success: false,
239
- path: SUPPORTED_CLIENTS[this.clientName].codeSettingPath,
240
- error: error instanceof Error ? error.message : String(error)
241
- });
242
- }
243
- }
244
-
245
- // Update settings for VS Code Insiders if installed
246
- if (isVSCodeInsidersInstalled) {
247
- try {
248
- const settingPath = SUPPORTED_CLIENTS[this.clientName].codeInsiderSettingPath;
249
- await this.setupClientSettings(settingPath, serverName, installConfig);
250
- results.push({ success: true, path: settingPath });
251
- } catch (error) {
252
- results.push({
253
- success: false,
254
- path: SUPPORTED_CLIENTS[this.clientName].codeInsiderSettingPath,
255
- error: error instanceof Error ? error.message : String(error)
256
- });
257
- }
258
- }
259
-
260
- return results;
261
- }
262
-
263
- /**
264
- * Install the client
265
- * @param serverConfig Server configuration
266
- * @param options Installation options including environment variables and arguments
267
- */
268
- async install(serverConfig: McpConfig, options: ServerInstallOptions, categoryName?: string): Promise<OperationStatus> {
269
- const operationId = this.generateOperationId();
270
-
271
- const recorder = InstallOperationManager.getInstance(categoryName || serverConfig.name, serverConfig.name);
272
- return await recorder.recording(
273
- async () => {
274
- await recorder.recording(
275
- () => this.checkVSCodeAndInstallExtension(operationId), {
276
- stepName: RecordingConstants.STEP_CHECK_VSCODE_AND_INSTALL_EXTENSION,
277
- onResult: (result) => result?.status !== 'failed'
278
- }
279
- )
280
-
281
- const installConfig = await recorder.recording(
282
- () => this.setupInstallConfig(serverConfig, options), {
283
- stepName: RecordingConstants.STEP_SETUP_INSTALLATION_CONFIG
284
- });
285
-
286
- if (serverConfig.mode) {
287
- installConfig.mode = serverConfig.mode;
288
- }
289
-
290
- const results = await recorder.recording(
291
- () => this.updateVSCodeSettings(serverConfig.name, installConfig), {
292
- stepName: RecordingConstants.STEP_UPDATE_VSCODE_SETTINGS,
293
- onResult: (result) => result?.some(r => r.success)
294
- }
295
- );
296
-
297
- // Determine overall success
298
- const anySuccess = results.some(r => r.success);
299
- const successPaths = results.filter(r => r.success).map(r => r.path);
300
- const errors = results.filter(r => !r.success).map(r => r.error);
301
-
302
- const finalMessage = anySuccess
303
- ? `Successfully installed ${this.clientName} client. Updated settings in: ${successPaths.join(', ')}`
304
- : `Failed to install ${this.clientName} client. Errors: ${errors.join('; ')}`;
305
-
306
- return {
307
- status: anySuccess ? 'completed' : 'failed',
308
- type: 'install',
309
- target: 'server',
310
- message: finalMessage,
311
- operationId,
312
- error: anySuccess ? undefined : errors.join('; ')
313
- };
314
- },
315
- {
316
- stepName: RecordingConstants.STEP_INSTALLATION,
317
- onResult: (result) => result?.status !== 'failed',
318
- endMessage: (result) => (result as OperationStatus)?.message,
319
- onError: (error) => {
320
- const errorMsg = `Unexpected error installing ${this.clientName} client: ${error instanceof Error ? error.message : String(error)}`;
321
- return {
322
- result: {
323
- status: 'failed',
324
- type: 'install',
325
- target: 'server',
326
- message: errorMsg,
327
- operationId,
328
- error: error instanceof Error ? error.message : String(error)
329
- }, message: errorMsg
330
- };
331
- }
332
- }
333
- );
334
-
335
- }
336
-
337
- /**
338
- * Abstract method that must be implemented by client-specific installers
339
- */
340
- abstract setupClientSettings(settingPath: string, serverName: string, installConfig: any): Promise<void>;
341
- }
@@ -1,222 +0,0 @@
1
- import { ConfigurationProvider } from '../../loaders/ConfigurationProvider.js';
2
- import { SUPPORTED_CLIENTS } from '../../metadatas/constants.js';
3
- import {
4
- ServerOperationResult,
5
- OperationStatus,
6
- ServerInstallOptions,
7
- McpConfig,
8
- RequirementStatus
9
- } from '../../metadatas/types.js';
10
- import { Logger } from '../../../utils/logger.js';
11
- import { ClientInstallerFactory } from './ClientInstallerFactory.js';
12
- import { InstallOperationManager } from '../../loaders/InstallOperationManager.js';
13
- import { stat } from 'fs';
14
-
15
- /**
16
- * Main client installer class that orchestrates client installation process
17
- * Handles requirements checking and delegates to specific client installers
18
- */
19
- export class ClientInstaller {
20
- private configProvider: ConfigurationProvider;
21
-
22
- constructor(
23
- private categoryName: string,
24
- private serverName: string,
25
- private clients: string[]
26
- ) {
27
- this.configProvider = ConfigurationProvider.getInstance();
28
- }
29
-
30
- /**
31
- * Install all specified clients
32
- */
33
- async install(options: ServerInstallOptions): Promise<ServerOperationResult> {
34
- const initialStatuses: OperationStatus[] = [];
35
-
36
- // Start installation for each client asynchronously
37
- const installPromises = this.clients.map(async (clientName) => {
38
- const status = await this.installClient(clientName, options);
39
- initialStatuses.push(status);
40
- return status;
41
- });
42
-
43
- // Wait for all installations to complete
44
- await Promise.all(installPromises);
45
-
46
- // Return result
47
- return {
48
- success: true,
49
- message: 'Client installations completed',
50
- status: initialStatuses
51
- };
52
- }
53
-
54
- /**
55
- * Install client with requirements checking
56
- */
57
- private async installClient(clientName: string, options: ServerInstallOptions): Promise<OperationStatus> {
58
- const operationId = this.generateOperationId();
59
-
60
- // Check if client is supported
61
- if (!ClientInstallerFactory.isClientSupported(clientName)) {
62
- return {
63
- status: 'failed',
64
- type: 'install',
65
- target: 'server',
66
- message: `Unsupported client: ${clientName}`,
67
- operationId
68
- };
69
- }
70
-
71
- // Create initial operation status
72
- const initialStatus: OperationStatus = {
73
- status: 'pending',
74
- type: 'install',
75
- target: 'server',
76
- message: `Initializing installation for client: ${clientName}`,
77
- operationId
78
- };
79
-
80
- // Async installation process
81
- this.processInstallation(clientName, operationId, options)
82
- .then((status) => {
83
- if (status.status === 'completed' || status.status === 'failed') {
84
- InstallOperationManager
85
- .getInstance(this.categoryName, this.serverName)
86
- .markOverallStatus(status.status)
87
- }
88
-
89
- this.configProvider.updateServerOperationStatus(
90
- this.categoryName,
91
- this.serverName,
92
- clientName,
93
- status
94
- );
95
- })
96
- .catch((error) => {
97
- this.configProvider.updateServerOperationStatus(
98
- this.categoryName,
99
- this.serverName,
100
- clientName,
101
- {
102
- status: 'failed',
103
- type: 'install',
104
- target: 'server',
105
- message: `Error installing client ${clientName}: ${error instanceof Error ? error.message : String(error)}`,
106
- operationId,
107
- error: error instanceof Error ? error.message : String(error)
108
- }
109
- );
110
- Logger.error(`Error installing client ${clientName}: ${error instanceof Error ? error.message : String(error)}`);
111
- InstallOperationManager
112
- .getInstance(this.categoryName, this.serverName)
113
- .markOverallStatus('failed', error)
114
- });
115
-
116
- // Update server status with initial client installation status
117
- await this.configProvider.updateServerOperationStatus(
118
- this.categoryName,
119
- this.serverName,
120
- clientName,
121
- initialStatus
122
- );
123
- return initialStatus;
124
- }
125
-
126
- private async processInstallation(clientName: string, operationId: string, options: ServerInstallOptions): Promise<OperationStatus> {
127
- const requirementsReady = await this.checkRequirements(operationId, clientName, options);
128
- if (!requirementsReady) {
129
- const failedStatus: OperationStatus = {
130
- status: 'failed',
131
- type: 'install',
132
- target: 'server',
133
- message: `Requirements not ready for client: ${clientName} after timeout`,
134
- operationId
135
- };
136
- return failedStatus;
137
- }
138
-
139
- // Create client-specific installer
140
- const installer = ClientInstallerFactory.getInstaller(clientName);
141
-
142
- if (!installer) {
143
- throw new Error(`Failed to create installer for client: ${clientName}`);
144
- }
145
-
146
- const serverConfig = await this.configProvider.getServerMcpConfig(this.categoryName, this.serverName);
147
- if (!serverConfig) {
148
- throw new Error(`Server configuration not found for category: ${this.categoryName}, server: ${this.serverName}`);
149
- }
150
-
151
- // If we've reached here, requirements are ready - update status to in-progress
152
- const inProgressStatus: OperationStatus = {
153
- status: 'in-progress',
154
- type: 'install',
155
- target: 'server',
156
- message: `Installing client: ${clientName}`,
157
- operationId: operationId
158
- };
159
-
160
- await this.configProvider.updateServerOperationStatus(
161
- this.categoryName,
162
- this.serverName,
163
- clientName,
164
- inProgressStatus
165
- );
166
- // Install client
167
- return await installer.install(serverConfig, options, this.categoryName);
168
- }
169
-
170
- /**
171
- * Generate a unique operation ID for tracking installations
172
- */
173
- private generateOperationId(): string {
174
- return `install-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
175
- }
176
-
177
- /**
178
- * Check if server requirements are ready
179
- * Waits for requirements to be ready with timeout
180
- */
181
- private async checkRequirements(operationId: string, clientName: string, options: ServerInstallOptions): Promise<boolean> {
182
- let requirementsReady = await this.configProvider.isRequirementsReady(this.categoryName, this.serverName);
183
-
184
- if (!requirementsReady) {
185
- const pendingStatus: OperationStatus = {
186
- status: 'pending',
187
- type: 'install',
188
- target: 'server',
189
- message: `Waiting for requirements to be ready for client: ${clientName}`,
190
- operationId
191
- };
192
-
193
- await this.configProvider.updateServerOperationStatus(
194
- this.categoryName,
195
- this.serverName,
196
- clientName,
197
- pendingStatus
198
- );
199
-
200
- // Set up periodic checking with timeout
201
- const startTime = Date.now();
202
- const timeoutMs = 5 * 60 * 1000; // 5 minutes
203
- const intervalMs = 5 * 1000; // 5 seconds
204
-
205
- while (!requirementsReady && (Date.now() - startTime) < timeoutMs) {
206
- await new Promise(resolve => setTimeout(resolve, intervalMs));
207
- requirementsReady = await this.configProvider.isRequirementsReady(this.categoryName, this.serverName);
208
- }
209
- }
210
-
211
- var requirementsStatus: RequirementStatus[] = await this.configProvider.GetServerRequirementStatus(this.categoryName, this.serverName);
212
-
213
- // Find first non-empty npmPath from requirements status
214
- const npmPathRequirement = requirementsStatus.find(status => status.npmPath && status.npmPath.length > 0);
215
- if (npmPathRequirement && npmPathRequirement.npmPath) {
216
- options.settings = options.settings || {};
217
- options.settings.npmPath = npmPathRequirement.npmPath;
218
- }
219
-
220
- return requirementsReady;
221
- }
222
- }
@@ -1,43 +0,0 @@
1
- import { MSRooCodeInstaller } from './MSRooCodeInstaller.js';
2
- import { ClineInstaller } from './ClineInstaller.js';
3
- import { GithubCopilotInstaller } from './GithubCopilotInstaller.js';
4
- import { BaseClientInstaller } from './BaseClientInstaller.js';
5
- import { SUPPORTED_CLIENTS } from '../../metadatas/constants.js';
6
-
7
- /**
8
- * Factory for creating client-specific installers
9
- * Handles creation of appropriate installer based on client type
10
- */
11
- export class ClientInstallerFactory {
12
- private static readonly installerMap: Record<string, new () => BaseClientInstaller> = {
13
- [Object.keys(SUPPORTED_CLIENTS)[0]]: MSRooCodeInstaller,
14
- [Object.keys(SUPPORTED_CLIENTS)[1]]: ClineInstaller,
15
- [Object.keys(SUPPORTED_CLIENTS)[2]]: GithubCopilotInstaller
16
- };
17
-
18
- /**
19
- * Get a client installer instance based on client type
20
- * @param clientName Name of the client to get installer for
21
- * @returns Client-specific installer instance or undefined if client not supported
22
- */
23
- static getInstaller(
24
- clientName: string
25
- ): BaseClientInstaller | undefined {
26
- // Check if client is supported
27
- if (!SUPPORTED_CLIENTS[clientName]) {
28
- return undefined;
29
- }
30
-
31
- const InstallerClass = this.installerMap[clientName as keyof typeof this.installerMap];
32
- return InstallerClass ? new InstallerClass() : undefined;
33
- }
34
-
35
- /**
36
- * Check if a client is supported
37
- * @param clientName Name of the client to check
38
- * @returns True if client is supported, false otherwise
39
- */
40
- static isClientSupported(clientName: string): boolean {
41
- return !!SUPPORTED_CLIENTS[clientName];
42
- }
43
- }
@@ -1,35 +0,0 @@
1
- import { BaseClientInstaller } from './BaseClientInstaller.js';
2
- import { readJsonFile, writeJsonFile } from '../../../utils/clientUtils.js';
3
-
4
- /**
5
- * Cline client installer implementation
6
- * Handles installation of Cline client including extension installation and settings configuration
7
- */
8
- export class ClineInstaller extends BaseClientInstaller {
9
- protected readonly clientName: string = 'Cline';
10
-
11
- /**
12
- * Set up Cline client settings
13
- * Updates VS Code settings with MCP server configuration
14
- */
15
- async setupClientSettings(settingPath: string, serverName: string, installConfig: any): Promise<void> {
16
- // Read existing settings
17
- const settings = await readJsonFile(settingPath, true);
18
-
19
- // Initialize settings with client-specific structure
20
- this.initializeSettings(settings);
21
-
22
- // Handle different modes
23
- if (installConfig.mode === 'stdio') {
24
- // Process config for Windows NPX if needed
25
- const finalConfig = await this.handleWindowsNpx(installConfig);
26
-
27
- await this.handleStdioMode(settings, serverName, finalConfig);
28
- } else if (installConfig.mode === 'sse') {
29
- this.handleSseMode(settings, serverName, installConfig);
30
- }
31
-
32
- // Write updated settings
33
- await writeJsonFile(settingPath, settings);
34
- }
35
- }