imcp 0.0.13 → 0.0.15
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/core/ConfigurationProvider.d.ts +1 -0
- package/dist/core/ConfigurationProvider.js +15 -0
- package/dist/core/InstallationService.js +2 -7
- package/dist/core/MCPManager.d.ts +11 -2
- package/dist/core/MCPManager.js +24 -1
- package/dist/core/RequirementService.js +2 -8
- package/dist/core/installers/clients/BaseClientInstaller.d.ts +51 -0
- package/dist/core/installers/clients/BaseClientInstaller.js +160 -0
- package/dist/core/installers/clients/ClientInstaller.d.ts +16 -8
- package/dist/core/installers/clients/ClientInstaller.js +77 -504
- package/dist/core/installers/clients/ClientInstallerFactory.d.ts +19 -0
- package/dist/core/installers/clients/ClientInstallerFactory.js +41 -0
- package/dist/core/installers/clients/ClineInstaller.d.ts +18 -0
- package/dist/core/installers/clients/ClineInstaller.js +124 -0
- package/dist/core/installers/clients/GithubCopilotInstaller.d.ts +34 -0
- package/dist/core/installers/clients/GithubCopilotInstaller.js +162 -0
- package/dist/core/installers/clients/MSRooCodeInstaller.d.ts +15 -0
- package/dist/core/installers/clients/MSRooCodeInstaller.js +122 -0
- package/dist/core/installers/requirements/BaseInstaller.d.ts +11 -34
- package/dist/core/installers/requirements/BaseInstaller.js +5 -116
- package/dist/core/installers/requirements/CommandInstaller.d.ts +6 -1
- package/dist/core/installers/requirements/CommandInstaller.js +7 -0
- package/dist/core/installers/requirements/GeneralInstaller.d.ts +6 -1
- package/dist/core/installers/requirements/GeneralInstaller.js +9 -4
- package/dist/core/installers/requirements/NpmInstaller.d.ts +46 -7
- package/dist/core/installers/requirements/NpmInstaller.js +150 -58
- package/dist/core/installers/requirements/PipInstaller.d.ts +9 -0
- package/dist/core/installers/requirements/PipInstaller.js +66 -28
- package/dist/core/onboard/FeedOnboardService.d.ts +72 -0
- package/dist/core/onboard/FeedOnboardService.js +312 -0
- package/dist/core/onboard/OnboardProcessor.d.ts +79 -0
- package/dist/core/onboard/OnboardProcessor.js +290 -0
- package/dist/core/onboard/OnboardStatus.d.ts +49 -0
- package/dist/core/onboard/OnboardStatus.js +10 -0
- package/dist/core/onboard/OnboardStatusManager.d.ts +57 -0
- package/dist/core/onboard/OnboardStatusManager.js +176 -0
- package/dist/core/types.d.ts +6 -6
- package/dist/core/validators/FeedValidator.d.ts +20 -0
- package/dist/core/validators/FeedValidator.js +80 -0
- package/dist/core/validators/IServerValidator.d.ts +19 -0
- package/dist/core/validators/IServerValidator.js +2 -0
- package/dist/core/validators/SSEServerValidator.d.ts +15 -0
- package/dist/core/validators/SSEServerValidator.js +39 -0
- package/dist/core/validators/ServerValidatorFactory.d.ts +24 -0
- package/dist/core/validators/ServerValidatorFactory.js +45 -0
- package/dist/core/validators/StdioServerValidator.d.ts +46 -0
- package/dist/core/validators/StdioServerValidator.js +229 -0
- package/dist/services/InstallRequestValidator.d.ts +1 -1
- package/dist/services/ServerService.d.ts +9 -6
- package/dist/services/ServerService.js +18 -7
- package/dist/utils/adoUtils.d.ts +29 -0
- package/dist/utils/adoUtils.js +252 -0
- package/dist/utils/clientUtils.d.ts +0 -7
- package/dist/utils/clientUtils.js +0 -42
- package/dist/utils/githubUtils.d.ts +10 -0
- package/dist/utils/githubUtils.js +22 -0
- package/dist/utils/macroExpressionUtils.d.ts +38 -0
- package/dist/utils/macroExpressionUtils.js +116 -0
- package/dist/utils/osUtils.d.ts +4 -20
- package/dist/utils/osUtils.js +78 -23
- package/dist/web/contract/serverContract.d.ts +66 -0
- package/dist/web/contract/serverContract.js +2 -0
- package/dist/web/public/css/notifications.css +48 -17
- package/dist/web/public/css/onboard.css +107 -0
- package/dist/web/public/index.html +90 -18
- package/dist/web/public/js/api.js +3 -6
- package/dist/web/public/js/flights/flights.js +127 -0
- package/dist/web/public/js/modal/index.js +58 -0
- package/dist/web/public/js/modal/installHandler.js +227 -0
- package/dist/web/public/js/modal/installModal.js +163 -0
- package/dist/web/public/js/modal/installation.js +281 -0
- package/dist/web/public/js/modal/loadingModal.js +52 -0
- package/dist/web/public/js/modal/loadingUI.js +74 -0
- package/dist/web/public/js/modal/messageQueue.js +112 -0
- package/dist/web/public/js/modal/modalSetup.js +513 -0
- package/dist/web/public/js/modal/modalUI.js +214 -0
- package/dist/web/public/js/modal/modalUtils.js +49 -0
- package/dist/web/public/js/modal/version.js +20 -0
- package/dist/web/public/js/modal/versionUtils.js +20 -0
- package/dist/web/public/js/modal.js +25 -1041
- package/dist/web/public/js/notifications.js +66 -27
- package/dist/web/public/js/onboard/ONBOARDING_PAGE_DESIGN.md +338 -0
- package/dist/web/public/js/onboard/formProcessor.js +864 -0
- package/dist/web/public/js/onboard/index.js +374 -0
- package/dist/web/public/js/onboard/publishHandler.js +132 -0
- package/dist/web/public/js/onboard/state.js +76 -0
- package/dist/web/public/js/onboard/templates.js +343 -0
- package/dist/web/public/js/onboard/uiHandlers.js +758 -0
- package/dist/web/public/js/onboard/validationHandlers.js +378 -0
- package/dist/web/public/js/serverCategoryDetails.js +43 -17
- package/dist/web/public/js/serverCategoryList.js +15 -2
- package/dist/web/public/onboard.html +296 -0
- package/dist/web/public/styles.css +91 -1
- package/dist/web/server.d.ts +0 -10
- package/dist/web/server.js +131 -22
- package/package.json +2 -2
- package/src/core/ConfigurationProvider.ts +15 -0
- package/src/core/InstallationService.ts +2 -7
- package/src/core/MCPManager.ts +26 -1
- package/src/core/RequirementService.ts +2 -9
- package/src/core/installers/clients/BaseClientInstaller.ts +196 -0
- package/src/core/installers/clients/ClientInstaller.ts +97 -589
- package/src/core/installers/clients/ClientInstallerFactory.ts +46 -0
- package/src/core/installers/clients/ClineInstaller.ts +135 -0
- package/src/core/installers/clients/GithubCopilotInstaller.ts +179 -0
- package/src/core/installers/clients/MSRooCodeInstaller.ts +133 -0
- package/src/core/installers/requirements/BaseInstaller.ts +13 -136
- package/src/core/installers/requirements/CommandInstaller.ts +9 -1
- package/src/core/installers/requirements/GeneralInstaller.ts +11 -4
- package/src/core/installers/requirements/NpmInstaller.ts +178 -61
- package/src/core/installers/requirements/PipInstaller.ts +68 -29
- package/src/core/onboard/FeedOnboardService.ts +346 -0
- package/src/core/onboard/OnboardProcessor.ts +305 -0
- package/src/core/onboard/OnboardStatus.ts +55 -0
- package/src/core/onboard/OnboardStatusManager.ts +188 -0
- package/src/core/types.ts +6 -6
- package/src/core/validators/FeedValidator.ts +79 -0
- package/src/core/validators/IServerValidator.ts +21 -0
- package/src/core/validators/SSEServerValidator.ts +43 -0
- package/src/core/validators/ServerValidatorFactory.ts +51 -0
- package/src/core/validators/StdioServerValidator.ts +259 -0
- package/src/services/InstallRequestValidator.ts +1 -1
- package/src/services/ServerService.ts +22 -7
- package/src/utils/adoUtils.ts +291 -0
- package/src/utils/clientUtils.ts +0 -44
- package/src/utils/githubUtils.ts +24 -0
- package/src/utils/macroExpressionUtils.ts +121 -0
- package/src/utils/osUtils.ts +89 -24
- package/src/web/contract/serverContract.ts +74 -0
- package/src/web/public/css/notifications.css +48 -17
- package/src/web/public/css/onboard.css +107 -0
- package/src/web/public/index.html +90 -18
- package/src/web/public/js/api.js +3 -6
- package/src/web/public/js/flights/flights.js +127 -0
- package/src/web/public/js/modal/index.js +58 -0
- package/src/web/public/js/modal/installModal.js +163 -0
- package/src/web/public/js/modal/installation.js +281 -0
- package/src/web/public/js/modal/loadingModal.js +52 -0
- package/src/web/public/js/modal/messageQueue.js +112 -0
- package/src/web/public/js/modal/modalSetup.js +513 -0
- package/src/web/public/js/modal/modalUtils.js +49 -0
- package/src/web/public/js/modal/versionUtils.js +20 -0
- package/src/web/public/js/modal.js +25 -1041
- package/src/web/public/js/notifications.js +66 -27
- package/src/web/public/js/onboard/ONBOARDING_PAGE_DESIGN.md +338 -0
- package/src/web/public/js/onboard/formProcessor.js +864 -0
- package/src/web/public/js/onboard/index.js +374 -0
- package/src/web/public/js/onboard/publishHandler.js +132 -0
- package/src/web/public/js/onboard/state.js +76 -0
- package/src/web/public/js/onboard/templates.js +343 -0
- package/src/web/public/js/onboard/uiHandlers.js +758 -0
- package/src/web/public/js/onboard/validationHandlers.js +378 -0
- package/src/web/public/js/serverCategoryDetails.js +43 -17
- package/src/web/public/js/serverCategoryList.js +15 -2
- package/src/web/public/onboard.html +296 -0
- package/src/web/public/styles.css +91 -1
- package/src/web/server.ts +167 -58
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { serverValidatorFactory } from "./ServerValidatorFactory.js";
|
|
2
|
+
import { Logger } from "../../utils/logger.js";
|
|
3
|
+
/**
|
|
4
|
+
* Validates feed configurations to ensure they meet required criteria
|
|
5
|
+
*/
|
|
6
|
+
export class FeedValidator {
|
|
7
|
+
/**
|
|
8
|
+
* Validates a feed configuration
|
|
9
|
+
* @param config The feed configuration to validate
|
|
10
|
+
* @returns true if valid, throws error if invalid
|
|
11
|
+
*/
|
|
12
|
+
validate(config) {
|
|
13
|
+
try {
|
|
14
|
+
Logger.debug(`Validating feed configuration: ${config.name}`);
|
|
15
|
+
// Validate required fields
|
|
16
|
+
if (!config.name)
|
|
17
|
+
throw new Error('Feed name is required');
|
|
18
|
+
if (!config.displayName)
|
|
19
|
+
throw new Error('Feed display name is required');
|
|
20
|
+
if (!config.description)
|
|
21
|
+
throw new Error('Feed description is required');
|
|
22
|
+
// Validate MCP servers array
|
|
23
|
+
if (!Array.isArray(config.mcpServers) || config.mcpServers.length === 0) {
|
|
24
|
+
throw new Error('Feed must contain at least one MCP server');
|
|
25
|
+
}
|
|
26
|
+
// Validate requirements if present
|
|
27
|
+
if (config.requirements) {
|
|
28
|
+
for (const req of config.requirements) {
|
|
29
|
+
if (!req.name)
|
|
30
|
+
throw new Error('Requirement name is required');
|
|
31
|
+
if (!req.type)
|
|
32
|
+
throw new Error('Requirement type is required');
|
|
33
|
+
if (!req.version)
|
|
34
|
+
throw new Error('Requirement version is required');
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
Logger.debug(`Feed configuration validation successful: ${config.name}`);
|
|
38
|
+
return true;
|
|
39
|
+
}
|
|
40
|
+
catch (error) {
|
|
41
|
+
const errorMsg = `Feed validation failed: ${error instanceof Error ? error.message : String(error)}`;
|
|
42
|
+
Logger.error(errorMsg);
|
|
43
|
+
throw new Error(errorMsg);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Validates a single MCP server configuration using the appropriate validator
|
|
48
|
+
* @param server The MCP server configuration to validate
|
|
49
|
+
* @param config The feed configuration containing shared requirements
|
|
50
|
+
* @returns true if valid, throws error if invalid
|
|
51
|
+
*/
|
|
52
|
+
async validateServer(server, config) {
|
|
53
|
+
try {
|
|
54
|
+
Logger.debug(`Validating server configuration: ${server.name}`);
|
|
55
|
+
// Validate basic required fields
|
|
56
|
+
if (!server.name)
|
|
57
|
+
throw new Error('Server name is required');
|
|
58
|
+
if (!server.description)
|
|
59
|
+
throw new Error('Server description is required');
|
|
60
|
+
if (!server.mode)
|
|
61
|
+
throw new Error('Server mode is required');
|
|
62
|
+
if (!server.installation)
|
|
63
|
+
throw new Error('Server installation configuration is required');
|
|
64
|
+
// Get the appropriate validator for this server type
|
|
65
|
+
const validator = serverValidatorFactory.getValidatorForServer(server);
|
|
66
|
+
// Perform mode-specific validation with feed config
|
|
67
|
+
await validator.validateServer(server, config);
|
|
68
|
+
Logger.debug(`Server configuration validation successful: ${server.name}`);
|
|
69
|
+
return true;
|
|
70
|
+
}
|
|
71
|
+
catch (error) {
|
|
72
|
+
const errorMsg = `Server validation failed: ${error instanceof Error ? error.message : String(error)}`;
|
|
73
|
+
Logger.error(errorMsg);
|
|
74
|
+
throw new Error(errorMsg);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
// Export singleton instance
|
|
79
|
+
export const feedValidator = new FeedValidator();
|
|
80
|
+
//# sourceMappingURL=FeedValidator.js.map
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { McpConfig, FeedConfiguration } from "../types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Interface for MCP server configuration validators
|
|
4
|
+
* Defines common validation operations for server configurations
|
|
5
|
+
*/
|
|
6
|
+
export interface IServerValidator {
|
|
7
|
+
/**
|
|
8
|
+
* Validates a specific MCP server configuration
|
|
9
|
+
* Implementation varies based on server mode (stdio/sse)
|
|
10
|
+
* @param server The MCP server configuration to validate
|
|
11
|
+
* @param config The feed configuration containing shared requirements
|
|
12
|
+
* @returns true if valid, throws error if invalid
|
|
13
|
+
*/
|
|
14
|
+
validateServer(server: McpConfig, config: FeedConfiguration): Promise<boolean>;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Valid validator types for MCP servers
|
|
18
|
+
*/
|
|
19
|
+
export type ValidatorType = 'stdio' | 'sse';
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { McpConfig, FeedConfiguration } from "../types.js";
|
|
2
|
+
import { IServerValidator } from "./IServerValidator.js";
|
|
3
|
+
/**
|
|
4
|
+
* Validates MCP server configurations for SSE mode
|
|
5
|
+
*/
|
|
6
|
+
export declare class SSEServerValidator implements IServerValidator {
|
|
7
|
+
/**
|
|
8
|
+
* Validates SSE-specific MCP server configuration
|
|
9
|
+
* Checks installation URL, requirements, and environment variables
|
|
10
|
+
* @param server The MCP server configuration to validate
|
|
11
|
+
* @param config The feed configuration containing shared requirements
|
|
12
|
+
* @returns true if valid, throws error if invalid
|
|
13
|
+
*/
|
|
14
|
+
validateServer(server: McpConfig, config: FeedConfiguration): Promise<boolean>;
|
|
15
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { Logger } from "../../utils/logger.js";
|
|
2
|
+
/**
|
|
3
|
+
* Validates MCP server configurations for SSE mode
|
|
4
|
+
*/
|
|
5
|
+
export class SSEServerValidator {
|
|
6
|
+
/**
|
|
7
|
+
* Validates SSE-specific MCP server configuration
|
|
8
|
+
* Checks installation URL, requirements, and environment variables
|
|
9
|
+
* @param server The MCP server configuration to validate
|
|
10
|
+
* @param config The feed configuration containing shared requirements
|
|
11
|
+
* @returns true if valid, throws error if invalid
|
|
12
|
+
*/
|
|
13
|
+
async validateServer(server, config) {
|
|
14
|
+
try {
|
|
15
|
+
Logger.debug(`Validating SSE server configuration: ${server.name}`);
|
|
16
|
+
if (!server.installation?.url) {
|
|
17
|
+
throw new Error('SSE server URL is required in installation configuration');
|
|
18
|
+
}
|
|
19
|
+
try {
|
|
20
|
+
new URL(server.installation.url);
|
|
21
|
+
}
|
|
22
|
+
catch (e) {
|
|
23
|
+
throw new Error(`Invalid SSE server URL: ${server.installation.url}`);
|
|
24
|
+
}
|
|
25
|
+
// Validate server mode
|
|
26
|
+
if (server.mode !== 'sse') {
|
|
27
|
+
throw new Error(`Invalid server mode for SSE validator: ${server.mode}`);
|
|
28
|
+
}
|
|
29
|
+
// Additional SSE-specific validation will be implemented later
|
|
30
|
+
return true;
|
|
31
|
+
}
|
|
32
|
+
catch (error) {
|
|
33
|
+
const errorMsg = `Server validation failed: ${error instanceof Error ? error.message : String(error)}`;
|
|
34
|
+
Logger.error(errorMsg);
|
|
35
|
+
throw new Error(errorMsg);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=SSEServerValidator.js.map
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { McpConfig } from "../types.js";
|
|
2
|
+
import { IServerValidator, ValidatorType } from "./IServerValidator.js";
|
|
3
|
+
/**
|
|
4
|
+
* Factory class for managing server validator instances
|
|
5
|
+
* Maintains a singleton map of validators by type
|
|
6
|
+
*/
|
|
7
|
+
export declare class ServerValidatorFactory {
|
|
8
|
+
private static validators;
|
|
9
|
+
constructor();
|
|
10
|
+
/**
|
|
11
|
+
* Gets the appropriate validator for the given server mode
|
|
12
|
+
* @param mode The server mode to get validator for
|
|
13
|
+
* @returns IServerValidator instance for the specified mode
|
|
14
|
+
* @throws Error if server mode is not supported
|
|
15
|
+
*/
|
|
16
|
+
getValidator(mode: ValidatorType): IServerValidator;
|
|
17
|
+
/**
|
|
18
|
+
* Gets the appropriate validator for the given server config
|
|
19
|
+
* @param serverConfig MCP server configuration
|
|
20
|
+
* @returns IServerValidator instance appropriate for the server mode
|
|
21
|
+
*/
|
|
22
|
+
getValidatorForServer(serverConfig: McpConfig): IServerValidator;
|
|
23
|
+
}
|
|
24
|
+
export declare const serverValidatorFactory: ServerValidatorFactory;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { StdioServerValidator } from "./StdioServerValidator.js";
|
|
2
|
+
import { SSEServerValidator } from "./SSEServerValidator.js";
|
|
3
|
+
import { Logger } from "../../utils/logger.js";
|
|
4
|
+
/**
|
|
5
|
+
* Factory class for managing server validator instances
|
|
6
|
+
* Maintains a singleton map of validators by type
|
|
7
|
+
*/
|
|
8
|
+
export class ServerValidatorFactory {
|
|
9
|
+
static validators = new Map();
|
|
10
|
+
constructor() {
|
|
11
|
+
// Initialize validators if not already done
|
|
12
|
+
if (ServerValidatorFactory.validators.size === 0) {
|
|
13
|
+
Logger.debug('Initializing server validators');
|
|
14
|
+
ServerValidatorFactory.validators.set('stdio', new StdioServerValidator());
|
|
15
|
+
ServerValidatorFactory.validators.set('sse', new SSEServerValidator());
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Gets the appropriate validator for the given server mode
|
|
20
|
+
* @param mode The server mode to get validator for
|
|
21
|
+
* @returns IServerValidator instance for the specified mode
|
|
22
|
+
* @throws Error if server mode is not supported
|
|
23
|
+
*/
|
|
24
|
+
getValidator(mode) {
|
|
25
|
+
const validator = ServerValidatorFactory.validators.get(mode);
|
|
26
|
+
if (!validator) {
|
|
27
|
+
const error = `Unsupported MCP server mode: ${mode}`;
|
|
28
|
+
Logger.error(error);
|
|
29
|
+
throw new Error(error);
|
|
30
|
+
}
|
|
31
|
+
Logger.debug(`Retrieved ${mode} validator`);
|
|
32
|
+
return validator;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Gets the appropriate validator for the given server config
|
|
36
|
+
* @param serverConfig MCP server configuration
|
|
37
|
+
* @returns IServerValidator instance appropriate for the server mode
|
|
38
|
+
*/
|
|
39
|
+
getValidatorForServer(serverConfig) {
|
|
40
|
+
return this.getValidator(serverConfig.mode);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
// Export singleton instance
|
|
44
|
+
export const serverValidatorFactory = new ServerValidatorFactory();
|
|
45
|
+
//# sourceMappingURL=ServerValidatorFactory.js.map
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { McpConfig, FeedConfiguration } from "../types.js";
|
|
2
|
+
import { IServerValidator } from "./IServerValidator.js";
|
|
3
|
+
/**
|
|
4
|
+
* Validates MCP server configurations for stdio mode
|
|
5
|
+
*/
|
|
6
|
+
export declare class StdioServerValidator implements IServerValidator {
|
|
7
|
+
private installerFactory;
|
|
8
|
+
/**
|
|
9
|
+
* Tests if a command exists and is executable
|
|
10
|
+
* @param command The command to test
|
|
11
|
+
* @returns true if command exists and is executable
|
|
12
|
+
*/
|
|
13
|
+
private isCommandExecutable;
|
|
14
|
+
/**
|
|
15
|
+
* Generates a dedicated folder path for a requirement.
|
|
16
|
+
* @param requirement The requirement configuration.
|
|
17
|
+
* @returns The path to the requirement's dedicated folder.
|
|
18
|
+
* @private
|
|
19
|
+
*/
|
|
20
|
+
private _getRequirementFolderPath;
|
|
21
|
+
/**
|
|
22
|
+
* Validates and installs a requirement if needed
|
|
23
|
+
* @param requirement The requirement config to validate and install
|
|
24
|
+
* @returns true if requirement is successfully installed/validated
|
|
25
|
+
*/
|
|
26
|
+
private validateRequirement;
|
|
27
|
+
/**
|
|
28
|
+
* Tests if a server can be started successfully with proper path resolution
|
|
29
|
+
* @param command The command to start the server
|
|
30
|
+
* @param args The command line arguments
|
|
31
|
+
* @returns Promise<boolean> true if server starts successfully, false otherwise
|
|
32
|
+
*
|
|
33
|
+
* Handles special cases:
|
|
34
|
+
* - For node commands: resolves ${NPMPATH} in arguments using resolveNpmModulePath
|
|
35
|
+
* - For python/python3 commands: resolves ${PYTHON_PACKAGE} in arguments using system Python packages
|
|
36
|
+
*/
|
|
37
|
+
private testServerStartup;
|
|
38
|
+
/**
|
|
39
|
+
* Validates stdio-specific MCP server configuration
|
|
40
|
+
* Checks command, arguments, dependencies and required environment variables
|
|
41
|
+
* @param server The MCP server configuration to validate
|
|
42
|
+
* @param config The feed configuration containing shared requirements
|
|
43
|
+
* @returns true if valid, throws error if invalid
|
|
44
|
+
*/
|
|
45
|
+
validateServer(server: McpConfig, config: FeedConfiguration): Promise<boolean>;
|
|
46
|
+
}
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
import { Logger } from "../../utils/logger.js";
|
|
2
|
+
import { createInstallerFactory } from "../installers/index.js";
|
|
3
|
+
import { exec, spawn } from 'child_process';
|
|
4
|
+
import util from 'util';
|
|
5
|
+
import { MACRO_EXPRESSIONS, resolveNpmModulePath } from "../../utils/macroExpressionUtils.js";
|
|
6
|
+
import { getSystemPythonPackageDirectory } from "../../utils/osUtils.js";
|
|
7
|
+
import { SETTINGS_DIR } from "../constants.js";
|
|
8
|
+
import path from "path";
|
|
9
|
+
const execPromise = util.promisify(exec);
|
|
10
|
+
/**
|
|
11
|
+
* Validates MCP server configurations for stdio mode
|
|
12
|
+
*/
|
|
13
|
+
export class StdioServerValidator {
|
|
14
|
+
installerFactory = createInstallerFactory();
|
|
15
|
+
/**
|
|
16
|
+
* Tests if a command exists and is executable
|
|
17
|
+
* @param command The command to test
|
|
18
|
+
* @returns true if command exists and is executable
|
|
19
|
+
*/
|
|
20
|
+
async isCommandExecutable(command) {
|
|
21
|
+
try {
|
|
22
|
+
Logger.debug(`Testing if command is executable: ${command}`);
|
|
23
|
+
const testCmd = process.platform === 'win32' ?
|
|
24
|
+
`where ${command}` :
|
|
25
|
+
`command -v ${command}`;
|
|
26
|
+
await execPromise(testCmd);
|
|
27
|
+
return true;
|
|
28
|
+
}
|
|
29
|
+
catch (error) {
|
|
30
|
+
Logger.debug(`Command not found: ${command}`);
|
|
31
|
+
return false;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Generates a dedicated folder path for a requirement.
|
|
36
|
+
* @param requirement The requirement configuration.
|
|
37
|
+
* @returns The path to the requirement's dedicated folder.
|
|
38
|
+
* @private
|
|
39
|
+
*/
|
|
40
|
+
_getRequirementFolderPath(requirement) {
|
|
41
|
+
return path.join(SETTINGS_DIR, 'onboard', 'npm_requirements', requirement.name, requirement.version.includes('latest') ? 'latest' : requirement.version);
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Validates and installs a requirement if needed
|
|
45
|
+
* @param requirement The requirement config to validate and install
|
|
46
|
+
* @returns true if requirement is successfully installed/validated
|
|
47
|
+
*/
|
|
48
|
+
async validateRequirement(requirement) {
|
|
49
|
+
try {
|
|
50
|
+
Logger.debug(`Validating/installing requirement: ${requirement.name}`);
|
|
51
|
+
const installer = this.installerFactory.getInstaller(requirement);
|
|
52
|
+
if (!installer) {
|
|
53
|
+
const msg = `No installer found for requirement type: ${requirement.type}`;
|
|
54
|
+
Logger.error(msg);
|
|
55
|
+
throw new Error(msg);
|
|
56
|
+
}
|
|
57
|
+
const targetDir = this._getRequirementFolderPath(requirement);
|
|
58
|
+
const status = await installer.install(requirement, { settings: { folderName: targetDir } });
|
|
59
|
+
if (!status.installed) {
|
|
60
|
+
const msg = `Failed to install requirement ${requirement.name}: ${status.error || 'Unknown error'}`;
|
|
61
|
+
Logger.error(msg);
|
|
62
|
+
throw new Error(msg);
|
|
63
|
+
}
|
|
64
|
+
Logger.debug(`Requirement ${requirement.name} is valid and installed`);
|
|
65
|
+
return true;
|
|
66
|
+
}
|
|
67
|
+
catch (error) {
|
|
68
|
+
const errorMsg = `Error validating/installing requirement ${requirement.name}: ${error instanceof Error ? error.message : String(error)}`;
|
|
69
|
+
Logger.error(errorMsg);
|
|
70
|
+
throw error instanceof Error ? error : new Error(errorMsg);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Tests if a server can be started successfully with proper path resolution
|
|
75
|
+
* @param command The command to start the server
|
|
76
|
+
* @param args The command line arguments
|
|
77
|
+
* @returns Promise<boolean> true if server starts successfully, false otherwise
|
|
78
|
+
*
|
|
79
|
+
* Handles special cases:
|
|
80
|
+
* - For node commands: resolves ${NPMPATH} in arguments using resolveNpmModulePath
|
|
81
|
+
* - For python/python3 commands: resolves ${PYTHON_PACKAGE} in arguments using system Python packages
|
|
82
|
+
*/
|
|
83
|
+
async testServerStartup(command, args, requirement) {
|
|
84
|
+
try {
|
|
85
|
+
// Log initial command and args
|
|
86
|
+
Logger.debug(`Testing server startup with command: ${command}`);
|
|
87
|
+
Logger.debug(`Original arguments: ${args.join(' ')}`);
|
|
88
|
+
// Handle path resolution based on command type
|
|
89
|
+
let finalArgs = [...args];
|
|
90
|
+
if (command === 'node') {
|
|
91
|
+
// Resolve npm module paths in arguments
|
|
92
|
+
Logger.debug('Resolving npm module paths in arguments');
|
|
93
|
+
const npmPath = requirement ? this._getRequirementFolderPath(requirement) : undefined;
|
|
94
|
+
finalArgs = args.map(arg => arg.replace(MACRO_EXPRESSIONS.NPMPATH, resolveNpmModulePath(npmPath)));
|
|
95
|
+
Logger.debug(`Resolved npm arguments: ${finalArgs.join(' ')}`);
|
|
96
|
+
}
|
|
97
|
+
else if (command === 'python' || command === 'python3') {
|
|
98
|
+
// Resolve Python package paths in arguments
|
|
99
|
+
Logger.debug('Resolving Python package paths in arguments');
|
|
100
|
+
const pythonDir = await getSystemPythonPackageDirectory();
|
|
101
|
+
if (pythonDir) {
|
|
102
|
+
finalArgs = args.map(arg => arg.includes('${PYTHON_PACKAGE}') ? arg.replace('${PYTHON_PACKAGE}', pythonDir) : arg);
|
|
103
|
+
Logger.debug(`Resolved Python arguments: ${finalArgs.join(' ')}`);
|
|
104
|
+
}
|
|
105
|
+
else {
|
|
106
|
+
const msg = 'Could not resolve system Python package directory';
|
|
107
|
+
Logger.error(msg);
|
|
108
|
+
throw new Error(msg);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
return await new Promise((resolve, reject) => {
|
|
112
|
+
Logger.debug(`Starting process with command: ${command} ${finalArgs.join(' ')}`);
|
|
113
|
+
// Set timeout for server startup test
|
|
114
|
+
const timeout = setTimeout(() => {
|
|
115
|
+
const msg = 'Server startup test timed out after 10 seconds';
|
|
116
|
+
Logger.error(msg);
|
|
117
|
+
serverProcess.kill();
|
|
118
|
+
reject(new Error(msg));
|
|
119
|
+
}, 20000);
|
|
120
|
+
// Start the server process
|
|
121
|
+
const serverProcess = spawn(command, finalArgs, {
|
|
122
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
123
|
+
shell: true
|
|
124
|
+
});
|
|
125
|
+
let output = '';
|
|
126
|
+
let errorOutput = '';
|
|
127
|
+
// Collect stdout
|
|
128
|
+
serverProcess.stdout.on('data', (data) => {
|
|
129
|
+
output += data.toString();
|
|
130
|
+
// If we see any output, consider it a success
|
|
131
|
+
clearTimeout(timeout);
|
|
132
|
+
serverProcess.kill();
|
|
133
|
+
resolve(true);
|
|
134
|
+
});
|
|
135
|
+
// Collect stderr
|
|
136
|
+
serverProcess.stderr.on('data', (data) => {
|
|
137
|
+
errorOutput += data.toString();
|
|
138
|
+
});
|
|
139
|
+
// Handle process exit
|
|
140
|
+
serverProcess.on('exit', (code) => {
|
|
141
|
+
clearTimeout(timeout);
|
|
142
|
+
if (code !== null && code !== 0) {
|
|
143
|
+
const msg = `Server startup failed with code ${code}: ${errorOutput}`;
|
|
144
|
+
Logger.error(msg);
|
|
145
|
+
reject(new Error(msg));
|
|
146
|
+
}
|
|
147
|
+
});
|
|
148
|
+
// Handle process error
|
|
149
|
+
serverProcess.on('error', (error) => {
|
|
150
|
+
clearTimeout(timeout);
|
|
151
|
+
const msg = `Server startup error: ${error.message}`;
|
|
152
|
+
Logger.error(msg);
|
|
153
|
+
reject(error);
|
|
154
|
+
});
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
catch (error) {
|
|
158
|
+
const msg = `Failed to test server startup: ${error instanceof Error ? error.message : String(error)}`;
|
|
159
|
+
Logger.error(msg);
|
|
160
|
+
throw error instanceof Error ? error : new Error(msg);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Validates stdio-specific MCP server configuration
|
|
165
|
+
* Checks command, arguments, dependencies and required environment variables
|
|
166
|
+
* @param server The MCP server configuration to validate
|
|
167
|
+
* @param config The feed configuration containing shared requirements
|
|
168
|
+
* @returns true if valid, throws error if invalid
|
|
169
|
+
*/
|
|
170
|
+
async validateServer(server, config) {
|
|
171
|
+
try {
|
|
172
|
+
Logger.debug(`Validating stdio server configuration: ${server.name}`);
|
|
173
|
+
// Check required installation command
|
|
174
|
+
if (!server.installation?.command) {
|
|
175
|
+
throw new Error('Server command is required in installation configuration');
|
|
176
|
+
}
|
|
177
|
+
// Validate server mode
|
|
178
|
+
if (server.mode !== 'stdio') {
|
|
179
|
+
throw new Error(`Invalid server mode for stdio validator: ${server.mode}`);
|
|
180
|
+
}
|
|
181
|
+
// Parse command and arguments
|
|
182
|
+
const fullCommand = server.installation.command;
|
|
183
|
+
const [baseCommand, ...defaultArgs] = fullCommand.split(' ');
|
|
184
|
+
const args = [...defaultArgs, ...(server.installation.args || [])];
|
|
185
|
+
// Validate command exists and is executable
|
|
186
|
+
const isExecutable = await this.isCommandExecutable(baseCommand);
|
|
187
|
+
if (!isExecutable) {
|
|
188
|
+
throw new Error(`Command not found or not executable: ${baseCommand}`);
|
|
189
|
+
}
|
|
190
|
+
// Validate required environment variables if specified
|
|
191
|
+
const envVars = server.installation.env;
|
|
192
|
+
if (envVars) {
|
|
193
|
+
for (const [name, varConfig] of Object.entries(envVars)) {
|
|
194
|
+
if (varConfig.Required && !varConfig.Default && !process.env[name]) {
|
|
195
|
+
throw new Error(`Required environment variable not set: ${name}`);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
// Validate dependencies if specified
|
|
200
|
+
if (server.dependencies?.requirements) {
|
|
201
|
+
Logger.debug(`Validating ${server.dependencies.requirements.length} requirements`);
|
|
202
|
+
for (const req of server.dependencies.requirements) {
|
|
203
|
+
const reqConfig = config.requirements?.find(r => r.name === req.name) || {
|
|
204
|
+
name: req.name,
|
|
205
|
+
version: req.version,
|
|
206
|
+
type: 'npm' // Default to npm if not specified
|
|
207
|
+
};
|
|
208
|
+
const isValid = await this.validateRequirement(reqConfig);
|
|
209
|
+
if (!isValid) {
|
|
210
|
+
throw new Error(`Dependency validation failed for: ${req.name}`);
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
// Test server startup
|
|
215
|
+
const serverStarted = await this.testServerStartup(baseCommand, args, config.requirements?.find(r => r.type === 'npm'));
|
|
216
|
+
if (!serverStarted) {
|
|
217
|
+
throw new Error(`Failed to start server with command: ${fullCommand} ${args.join(' ')}`);
|
|
218
|
+
}
|
|
219
|
+
Logger.debug(`Stdio server validation successful: ${server.name}`);
|
|
220
|
+
return true;
|
|
221
|
+
}
|
|
222
|
+
catch (error) {
|
|
223
|
+
const errorMsg = `Server validation failed: ${error instanceof Error ? error.message : String(error)}`;
|
|
224
|
+
Logger.error(errorMsg);
|
|
225
|
+
throw new Error(errorMsg);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
//# sourceMappingURL=StdioServerValidator.js.map
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ServerInstallOptions } from '../core/types.js';
|
|
2
|
-
import { InstallServersRequestBody } from '../web/
|
|
2
|
+
import { InstallServersRequestBody } from '../web/contract/serverContract.js';
|
|
3
3
|
export declare class InstallRequestValidator {
|
|
4
4
|
private serverFeedConfigs;
|
|
5
5
|
private feedDirectory;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { ServerSchema } from '../core/ServerSchemaProvider.js';
|
|
2
|
-
import { MCPServerCategory, ServerInstallOptions, ServerCategoryListOptions, ServerOperationResult, ServerUninstallOptions } from '../core/types.js';
|
|
2
|
+
import { MCPServerCategory, ServerInstallOptions, ServerCategoryListOptions, ServerOperationResult, ServerUninstallOptions, FeedConfiguration } from '../core/types.js';
|
|
3
|
+
import { OperationStatus } from '../core/onboard/OnboardStatus.js';
|
|
3
4
|
/**
|
|
4
5
|
* ServerService provides a unified interface for server management operations.
|
|
5
6
|
* This layer handles business logic that's shared between the CLI and web interface.
|
|
@@ -25,13 +26,8 @@ export declare class ServerService {
|
|
|
25
26
|
getServerSchema(categoryName: string, serverName: string): Promise<ServerSchema | undefined>;
|
|
26
27
|
/**
|
|
27
28
|
* Installs a specific mcp tool for a server.
|
|
28
|
-
* TODO: This might require enhancing MCPManager to handle category-specific installs.
|
|
29
29
|
*/
|
|
30
30
|
installMcpServer(category: string, serverName: string, options?: ServerInstallOptions): Promise<ServerOperationResult>;
|
|
31
|
-
/**
|
|
32
|
-
* Installs a specific mcp tool for a server.
|
|
33
|
-
* TODO: This might require enhancing MCPManager to handle category-specific installs.
|
|
34
|
-
*/
|
|
35
31
|
/**
|
|
36
32
|
* Uninstall MCP server from specified client targets
|
|
37
33
|
* @param category The server category
|
|
@@ -54,5 +50,12 @@ export declare class ServerService {
|
|
|
54
50
|
* Syncs MCP server configurations from remote feed source
|
|
55
51
|
*/
|
|
56
52
|
syncFeeds(): Promise<void>;
|
|
53
|
+
/**
|
|
54
|
+
* Onboards a new feed configuration
|
|
55
|
+
* @param config Feed configuration to onboard
|
|
56
|
+
*/
|
|
57
|
+
onboardFeed(config: FeedConfiguration): Promise<OperationStatus & {
|
|
58
|
+
feedConfiguration?: FeedConfiguration;
|
|
59
|
+
}>;
|
|
57
60
|
}
|
|
58
61
|
export declare const serverService: ServerService;
|
|
@@ -113,10 +113,8 @@ export class ServerService {
|
|
|
113
113
|
}
|
|
114
114
|
/**
|
|
115
115
|
* Installs a specific mcp tool for a server.
|
|
116
|
-
* TODO: This might require enhancing MCPManager to handle category-specific installs.
|
|
117
116
|
*/
|
|
118
|
-
async installMcpServer(category, serverName, options = {}
|
|
119
|
-
) {
|
|
117
|
+
async installMcpServer(category, serverName, options = {}) {
|
|
120
118
|
Logger.debug(`Installing MCP server: ${JSON.stringify({ category, serverName, options })}`);
|
|
121
119
|
try {
|
|
122
120
|
const result = await mcpManager.installServer(category, serverName, options);
|
|
@@ -128,10 +126,6 @@ export class ServerService {
|
|
|
128
126
|
throw error;
|
|
129
127
|
}
|
|
130
128
|
}
|
|
131
|
-
/**
|
|
132
|
-
* Installs a specific mcp tool for a server.
|
|
133
|
-
* TODO: This might require enhancing MCPManager to handle category-specific installs.
|
|
134
|
-
*/
|
|
135
129
|
/**
|
|
136
130
|
* Uninstall MCP server from specified client targets
|
|
137
131
|
* @param category The server category
|
|
@@ -185,6 +179,23 @@ export class ServerService {
|
|
|
185
179
|
async syncFeeds() {
|
|
186
180
|
return mcpManager.syncFeeds();
|
|
187
181
|
}
|
|
182
|
+
/**
|
|
183
|
+
* Onboards a new feed configuration
|
|
184
|
+
* @param config Feed configuration to onboard
|
|
185
|
+
*/
|
|
186
|
+
async onboardFeed(config) {
|
|
187
|
+
try {
|
|
188
|
+
const result = await mcpManager.onboardFeed(config);
|
|
189
|
+
// Log based on the operation status, e.g., if it's pending or succeeded.
|
|
190
|
+
// The actual "success" of onboarding is a multi-step process (PR creation, merge).
|
|
191
|
+
Logger.log(`Feed onboarding process for '${config.name}' initiated with status: ${result.status}, ID: ${result.onboardingId}`);
|
|
192
|
+
return result;
|
|
193
|
+
}
|
|
194
|
+
catch (error) {
|
|
195
|
+
Logger.error(`Failed to initiate feed onboarding for '${config.name}':`, error);
|
|
196
|
+
throw error; // Or return a specific error status object
|
|
197
|
+
}
|
|
198
|
+
}
|
|
188
199
|
}
|
|
189
200
|
// Export a singleton instance
|
|
190
201
|
export const serverService = new ServerService();
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { RequirementConfig, RegistryConfig } from '../core/types.js';
|
|
2
|
+
export interface AdoArtifactResult {
|
|
3
|
+
type: 'npm' | 'pip';
|
|
4
|
+
package: string;
|
|
5
|
+
registryUrl: string;
|
|
6
|
+
folderPath?: string;
|
|
7
|
+
version: string;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Handles fetching and setting up an Azure DevOps artifact.
|
|
11
|
+
* @param requirement The requirement configuration.
|
|
12
|
+
* @param registry The Azure DevOps artifacts registry configuration.
|
|
13
|
+
* @param pythonCommand Optional Python command (e.g., 'python', 'python3') for pip operations.
|
|
14
|
+
* @param targetDir Optional target directory for npm artifact setup. If not provided, a default will be used.
|
|
15
|
+
* @returns A promise that resolves with the artifact details.
|
|
16
|
+
*/
|
|
17
|
+
export declare function handleArtifact(requirement: RequirementConfig, registry: RegistryConfig['artifacts'], pythonCommand?: string, // Default to 'python' if not provided
|
|
18
|
+
targetDir?: string): Promise<AdoArtifactResult>;
|
|
19
|
+
/**
|
|
20
|
+
* Get the latest version of an artifact from Azure DevOps.
|
|
21
|
+
* This is a simplified implementation and might require further enhancements for robust authentication and error handling.
|
|
22
|
+
* @param execPromise The promise-based exec function.
|
|
23
|
+
* @param requirement The requirement configuration.
|
|
24
|
+
* @param registry The Azure DevOps artifacts registry configuration.
|
|
25
|
+
* @param options Optional server install options (e.g., for pythonCommand).
|
|
26
|
+
* @returns The latest version string, or undefined if not found or an error occurs.
|
|
27
|
+
*/
|
|
28
|
+
export declare function getArtifactLatestVersion(requirement: RequirementConfig, registry: RegistryConfig['artifacts'], options?: import('../core/types.js').ServerInstallOptions, // Added import for ServerInstallOptions
|
|
29
|
+
targetDir?: string): Promise<string | undefined>;
|