@local-labs-jpollock/local-cli 0.0.1
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/addon-dist/bin/mcp-stdio.js +2808 -0
- package/addon-dist/lib/common/constants.d.ts +22 -0
- package/addon-dist/lib/common/constants.js +26 -0
- package/addon-dist/lib/common/theme.d.ts +68 -0
- package/addon-dist/lib/common/theme.js +126 -0
- package/addon-dist/lib/common/types.d.ts +298 -0
- package/addon-dist/lib/common/types.js +6 -0
- package/addon-dist/lib/main/config/ConnectionInfo.d.ts +25 -0
- package/addon-dist/lib/main/config/ConnectionInfo.js +82 -0
- package/addon-dist/lib/main/index.d.ts +12 -0
- package/addon-dist/lib/main/index.js +3322 -0
- package/addon-dist/lib/main/mcp/McpAuth.d.ts +37 -0
- package/addon-dist/lib/main/mcp/McpAuth.js +87 -0
- package/addon-dist/lib/main/mcp/McpServer.d.ts +67 -0
- package/addon-dist/lib/main/mcp/McpServer.js +343 -0
- package/addon-dist/lib/main/mcp/tools/changePhpVersion.d.ts +7 -0
- package/addon-dist/lib/main/mcp/tools/changePhpVersion.js +81 -0
- package/addon-dist/lib/main/mcp/tools/cloneSite.d.ts +7 -0
- package/addon-dist/lib/main/mcp/tools/cloneSite.js +66 -0
- package/addon-dist/lib/main/mcp/tools/createSite.d.ts +7 -0
- package/addon-dist/lib/main/mcp/tools/createSite.js +137 -0
- package/addon-dist/lib/main/mcp/tools/deleteSite.d.ts +7 -0
- package/addon-dist/lib/main/mcp/tools/deleteSite.js +72 -0
- package/addon-dist/lib/main/mcp/tools/exportDatabase.d.ts +7 -0
- package/addon-dist/lib/main/mcp/tools/exportDatabase.js +72 -0
- package/addon-dist/lib/main/mcp/tools/exportSite.d.ts +7 -0
- package/addon-dist/lib/main/mcp/tools/exportSite.js +103 -0
- package/addon-dist/lib/main/mcp/tools/getLocalInfo.d.ts +7 -0
- package/addon-dist/lib/main/mcp/tools/getLocalInfo.js +72 -0
- package/addon-dist/lib/main/mcp/tools/getSite.d.ts +7 -0
- package/addon-dist/lib/main/mcp/tools/getSite.js +68 -0
- package/addon-dist/lib/main/mcp/tools/getSiteLogs.d.ts +7 -0
- package/addon-dist/lib/main/mcp/tools/getSiteLogs.js +149 -0
- package/addon-dist/lib/main/mcp/tools/helpers.d.ts +59 -0
- package/addon-dist/lib/main/mcp/tools/helpers.js +179 -0
- package/addon-dist/lib/main/mcp/tools/importDatabase.d.ts +7 -0
- package/addon-dist/lib/main/mcp/tools/importDatabase.js +109 -0
- package/addon-dist/lib/main/mcp/tools/importSite.d.ts +7 -0
- package/addon-dist/lib/main/mcp/tools/importSite.js +149 -0
- package/addon-dist/lib/main/mcp/tools/index.d.ts +26 -0
- package/addon-dist/lib/main/mcp/tools/index.js +117 -0
- package/addon-dist/lib/main/mcp/tools/listBlueprints.d.ts +7 -0
- package/addon-dist/lib/main/mcp/tools/listBlueprints.js +54 -0
- package/addon-dist/lib/main/mcp/tools/listServices.d.ts +7 -0
- package/addon-dist/lib/main/mcp/tools/listServices.js +112 -0
- package/addon-dist/lib/main/mcp/tools/listSites.d.ts +7 -0
- package/addon-dist/lib/main/mcp/tools/listSites.js +62 -0
- package/addon-dist/lib/main/mcp/tools/openAdminer.d.ts +7 -0
- package/addon-dist/lib/main/mcp/tools/openAdminer.js +59 -0
- package/addon-dist/lib/main/mcp/tools/openSite.d.ts +7 -0
- package/addon-dist/lib/main/mcp/tools/openSite.js +62 -0
- package/addon-dist/lib/main/mcp/tools/renameSite.d.ts +7 -0
- package/addon-dist/lib/main/mcp/tools/renameSite.js +70 -0
- package/addon-dist/lib/main/mcp/tools/restartSite.d.ts +7 -0
- package/addon-dist/lib/main/mcp/tools/restartSite.js +56 -0
- package/addon-dist/lib/main/mcp/tools/saveBlueprint.d.ts +7 -0
- package/addon-dist/lib/main/mcp/tools/saveBlueprint.js +89 -0
- package/addon-dist/lib/main/mcp/tools/startSite.d.ts +7 -0
- package/addon-dist/lib/main/mcp/tools/startSite.js +54 -0
- package/addon-dist/lib/main/mcp/tools/stopSite.d.ts +7 -0
- package/addon-dist/lib/main/mcp/tools/stopSite.js +54 -0
- package/addon-dist/lib/main/mcp/tools/toggleXdebug.d.ts +7 -0
- package/addon-dist/lib/main/mcp/tools/toggleXdebug.js +69 -0
- package/addon-dist/lib/main/mcp/tools/trustSsl.d.ts +7 -0
- package/addon-dist/lib/main/mcp/tools/trustSsl.js +59 -0
- package/addon-dist/lib/main/mcp/tools/wpCli.d.ts +7 -0
- package/addon-dist/lib/main/mcp/tools/wpCli.js +110 -0
- package/addon-dist/lib/main.d.ts +1 -0
- package/addon-dist/lib/main.js +10 -0
- package/addon-dist/lib/renderer/index.d.ts +7 -0
- package/addon-dist/lib/renderer/index.js +479 -0
- package/addon-dist/package.json +73 -0
- package/bin/lwp.js +10 -0
- package/lib/bootstrap/index.d.ts +98 -0
- package/lib/bootstrap/index.js +493 -0
- package/lib/bootstrap/paths.d.ts +28 -0
- package/lib/bootstrap/paths.js +96 -0
- package/lib/client/GraphQLClient.d.ts +38 -0
- package/lib/client/GraphQLClient.js +71 -0
- package/lib/client/index.d.ts +4 -0
- package/lib/client/index.js +10 -0
- package/lib/formatters/index.d.ts +75 -0
- package/lib/formatters/index.js +139 -0
- package/lib/index.d.ts +8 -0
- package/lib/index.js +1173 -0
- package/package.json +72 -0
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP Authentication Manager
|
|
3
|
+
* Handles token generation and validation
|
|
4
|
+
*/
|
|
5
|
+
export declare class McpAuth {
|
|
6
|
+
private token;
|
|
7
|
+
private logger;
|
|
8
|
+
constructor(logger: any);
|
|
9
|
+
/**
|
|
10
|
+
* Generate a new authentication token
|
|
11
|
+
*/
|
|
12
|
+
generateToken(): string;
|
|
13
|
+
/**
|
|
14
|
+
* Get current token or generate if not exists
|
|
15
|
+
*/
|
|
16
|
+
getToken(): string;
|
|
17
|
+
/**
|
|
18
|
+
* Set token (for loading from saved config)
|
|
19
|
+
*/
|
|
20
|
+
setToken(token: string): void;
|
|
21
|
+
/**
|
|
22
|
+
* Regenerate the authentication token
|
|
23
|
+
*/
|
|
24
|
+
regenerateToken(): string;
|
|
25
|
+
/**
|
|
26
|
+
* Validate provided token against stored token
|
|
27
|
+
*/
|
|
28
|
+
validateToken(providedToken: string | undefined): boolean;
|
|
29
|
+
/**
|
|
30
|
+
* Validate that request comes from trusted IP
|
|
31
|
+
*/
|
|
32
|
+
validateIP(ip: string | undefined): boolean;
|
|
33
|
+
/**
|
|
34
|
+
* Extract Bearer token from Authorization header
|
|
35
|
+
*/
|
|
36
|
+
extractBearerToken(authHeader: string | undefined): string | undefined;
|
|
37
|
+
}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* MCP Authentication Manager
|
|
4
|
+
* Handles token generation and validation
|
|
5
|
+
*/
|
|
6
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
7
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
8
|
+
};
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.McpAuth = void 0;
|
|
11
|
+
const crypto_1 = __importDefault(require("crypto"));
|
|
12
|
+
const constants_1 = require("../../common/constants");
|
|
13
|
+
class McpAuth {
|
|
14
|
+
constructor(logger) {
|
|
15
|
+
this.token = null;
|
|
16
|
+
this.logger = logger;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Generate a new authentication token
|
|
20
|
+
*/
|
|
21
|
+
generateToken() {
|
|
22
|
+
this.token = crypto_1.default.randomBytes(constants_1.AUTH_TOKEN_LENGTH / 2).toString('base64');
|
|
23
|
+
this.logger.info(`[MCP] Generated new authentication token: ${this.token.substring(0, 20)}...`);
|
|
24
|
+
return this.token;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Get current token or generate if not exists
|
|
28
|
+
*/
|
|
29
|
+
getToken() {
|
|
30
|
+
if (!this.token) {
|
|
31
|
+
return this.generateToken();
|
|
32
|
+
}
|
|
33
|
+
return this.token;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Set token (for loading from saved config)
|
|
37
|
+
*/
|
|
38
|
+
setToken(token) {
|
|
39
|
+
this.token = token;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Regenerate the authentication token
|
|
43
|
+
*/
|
|
44
|
+
regenerateToken() {
|
|
45
|
+
this.logger.info('[MCP] Regenerating authentication token');
|
|
46
|
+
return this.generateToken();
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Validate provided token against stored token
|
|
50
|
+
*/
|
|
51
|
+
validateToken(providedToken) {
|
|
52
|
+
if (!this.token || !providedToken) {
|
|
53
|
+
this.logger.warn(`[MCP Auth] Validation failed: token=${!!this.token}, provided=${!!providedToken}`);
|
|
54
|
+
return false;
|
|
55
|
+
}
|
|
56
|
+
// Support both raw token and Bearer prefix
|
|
57
|
+
const rawToken = providedToken.startsWith('Bearer ') ? providedToken.slice(7) : providedToken;
|
|
58
|
+
const isValid = rawToken === this.token;
|
|
59
|
+
if (!isValid) {
|
|
60
|
+
this.logger.warn(`[MCP Auth] Token mismatch: provided=${rawToken.substring(0, 20)}... stored=${this.token.substring(0, 20)}...`);
|
|
61
|
+
}
|
|
62
|
+
return isValid;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Validate that request comes from trusted IP
|
|
66
|
+
*/
|
|
67
|
+
validateIP(ip) {
|
|
68
|
+
if (!ip) {
|
|
69
|
+
return false;
|
|
70
|
+
}
|
|
71
|
+
return constants_1.TRUSTED_IPS.includes(ip);
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Extract Bearer token from Authorization header
|
|
75
|
+
*/
|
|
76
|
+
extractBearerToken(authHeader) {
|
|
77
|
+
if (!authHeader) {
|
|
78
|
+
return undefined;
|
|
79
|
+
}
|
|
80
|
+
if (authHeader.startsWith('Bearer ')) {
|
|
81
|
+
return authHeader.slice(7);
|
|
82
|
+
}
|
|
83
|
+
return authHeader;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
exports.McpAuth = McpAuth;
|
|
87
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiTWNwQXV0aC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9tYWluL21jcC9NY3BBdXRoLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQTs7O0dBR0c7Ozs7OztBQUVILG9EQUE0QjtBQUM1QixzREFBd0U7QUFFeEUsTUFBYSxPQUFPO0lBSWxCLFlBQVksTUFBVztRQUhmLFVBQUssR0FBa0IsSUFBSSxDQUFDO1FBSWxDLElBQUksQ0FBQyxNQUFNLEdBQUcsTUFBTSxDQUFDO0lBQ3ZCLENBQUM7SUFFRDs7T0FFRztJQUNILGFBQWE7UUFDWCxJQUFJLENBQUMsS0FBSyxHQUFHLGdCQUFNLENBQUMsV0FBVyxDQUFDLDZCQUFpQixHQUFHLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxRQUFRLENBQUMsQ0FBQztRQUMxRSxJQUFJLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyw2Q0FBNkMsSUFBSSxDQUFDLEtBQUssQ0FBQyxTQUFTLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUNoRyxPQUFPLElBQUksQ0FBQyxLQUFLLENBQUM7SUFDcEIsQ0FBQztJQUVEOztPQUVHO0lBQ0gsUUFBUTtRQUNOLElBQUksQ0FBQyxJQUFJLENBQUMsS0FBSyxFQUFFLENBQUM7WUFDaEIsT0FBTyxJQUFJLENBQUMsYUFBYSxFQUFFLENBQUM7UUFDOUIsQ0FBQztRQUNELE9BQU8sSUFBSSxDQUFDLEtBQUssQ0FBQztJQUNwQixDQUFDO0lBRUQ7O09BRUc7SUFDSCxRQUFRLENBQUMsS0FBYTtRQUNwQixJQUFJLENBQUMsS0FBSyxHQUFHLEtBQUssQ0FBQztJQUNyQixDQUFDO0lBRUQ7O09BRUc7SUFDSCxlQUFlO1FBQ2IsSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMseUNBQXlDLENBQUMsQ0FBQztRQUM1RCxPQUFPLElBQUksQ0FBQyxhQUFhLEVBQUUsQ0FBQztJQUM5QixDQUFDO0lBRUQ7O09BRUc7SUFDSCxhQUFhLENBQUMsYUFBaUM7UUFDN0MsSUFBSSxDQUFDLElBQUksQ0FBQyxLQUFLLElBQUksQ0FBQyxhQUFhLEVBQUUsQ0FBQztZQUNsQyxJQUFJLENBQUMsTUFBTSxDQUFDLElBQUksQ0FDZCx1Q0FBdUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxLQUFLLGNBQWMsQ0FBQyxDQUFDLGFBQWEsRUFBRSxDQUNuRixDQUFDO1lBQ0YsT0FBTyxLQUFLLENBQUM7UUFDZixDQUFDO1FBRUQsMkNBQTJDO1FBQzNDLE1BQU0sUUFBUSxHQUFHLGFBQWEsQ0FBQyxVQUFVLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxDQUFDLGFBQWEsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLGFBQWEsQ0FBQztRQUU5RixNQUFNLE9BQU8sR0FBRyxRQUFRLEtBQUssSUFBSSxDQUFDLEtBQUssQ0FBQztRQUN4QyxJQUFJLENBQUMsT0FBTyxFQUFFLENBQUM7WUFDYixJQUFJLENBQUMsTUFBTSxDQUFDLElBQUksQ0FDZCx1Q0FBdUMsUUFBUSxDQUFDLFNBQVMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLGNBQWMsSUFBSSxDQUFDLEtBQUssQ0FBQyxTQUFTLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxLQUFLLENBQy9HLENBQUM7UUFDSixDQUFDO1FBQ0QsT0FBTyxPQUFPLENBQUM7SUFDakIsQ0FBQztJQUVEOztPQUVHO0lBQ0gsVUFBVSxDQUFDLEVBQXNCO1FBQy9CLElBQUksQ0FBQyxFQUFFLEVBQUUsQ0FBQztZQUNSLE9BQU8sS0FBSyxDQUFDO1FBQ2YsQ0FBQztRQUNELE9BQVEsdUJBQWlDLENBQUMsUUFBUSxDQUFDLEVBQUUsQ0FBQyxDQUFDO0lBQ3pELENBQUM7SUFFRDs7T0FFRztJQUNILGtCQUFrQixDQUFDLFVBQThCO1FBQy9DLElBQUksQ0FBQyxVQUFVLEVBQUUsQ0FBQztZQUNoQixPQUFPLFNBQVMsQ0FBQztRQUNuQixDQUFDO1FBRUQsSUFBSSxVQUFVLENBQUMsVUFBVSxDQUFDLFNBQVMsQ0FBQyxFQUFFLENBQUM7WUFDckMsT0FBTyxVQUFVLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQzdCLENBQUM7UUFFRCxPQUFPLFVBQVUsQ0FBQztJQUNwQixDQUFDO0NBQ0Y7QUF6RkQsMEJBeUZDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBNQ1AgQXV0aGVudGljYXRpb24gTWFuYWdlclxuICogSGFuZGxlcyB0b2tlbiBnZW5lcmF0aW9uIGFuZCB2YWxpZGF0aW9uXG4gKi9cblxuaW1wb3J0IGNyeXB0byBmcm9tICdjcnlwdG8nO1xuaW1wb3J0IHsgQVVUSF9UT0tFTl9MRU5HVEgsIFRSVVNURURfSVBTIH0gZnJvbSAnLi4vLi4vY29tbW9uL2NvbnN0YW50cyc7XG5cbmV4cG9ydCBjbGFzcyBNY3BBdXRoIHtcbiAgcHJpdmF0ZSB0b2tlbjogc3RyaW5nIHwgbnVsbCA9IG51bGw7XG4gIHByaXZhdGUgbG9nZ2VyOiBhbnk7XG5cbiAgY29uc3RydWN0b3IobG9nZ2VyOiBhbnkpIHtcbiAgICB0aGlzLmxvZ2dlciA9IGxvZ2dlcjtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZW5lcmF0ZSBhIG5ldyBhdXRoZW50aWNhdGlvbiB0b2tlblxuICAgKi9cbiAgZ2VuZXJhdGVUb2tlbigpOiBzdHJpbmcge1xuICAgIHRoaXMudG9rZW4gPSBjcnlwdG8ucmFuZG9tQnl0ZXMoQVVUSF9UT0tFTl9MRU5HVEggLyAyKS50b1N0cmluZygnYmFzZTY0Jyk7XG4gICAgdGhpcy5sb2dnZXIuaW5mbyhgW01DUF0gR2VuZXJhdGVkIG5ldyBhdXRoZW50aWNhdGlvbiB0b2tlbjogJHt0aGlzLnRva2VuLnN1YnN0cmluZygwLCAyMCl9Li4uYCk7XG4gICAgcmV0dXJuIHRoaXMudG9rZW47XG4gIH1cblxuICAvKipcbiAgICogR2V0IGN1cnJlbnQgdG9rZW4gb3IgZ2VuZXJhdGUgaWYgbm90IGV4aXN0c1xuICAgKi9cbiAgZ2V0VG9rZW4oKTogc3RyaW5nIHtcbiAgICBpZiAoIXRoaXMudG9rZW4pIHtcbiAgICAgIHJldHVybiB0aGlzLmdlbmVyYXRlVG9rZW4oKTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMudG9rZW47XG4gIH1cblxuICAvKipcbiAgICogU2V0IHRva2VuIChmb3IgbG9hZGluZyBmcm9tIHNhdmVkIGNvbmZpZylcbiAgICovXG4gIHNldFRva2VuKHRva2VuOiBzdHJpbmcpOiB2b2lkIHtcbiAgICB0aGlzLnRva2VuID0gdG9rZW47XG4gIH1cblxuICAvKipcbiAgICogUmVnZW5lcmF0ZSB0aGUgYXV0aGVudGljYXRpb24gdG9rZW5cbiAgICovXG4gIHJlZ2VuZXJhdGVUb2tlbigpOiBzdHJpbmcge1xuICAgIHRoaXMubG9nZ2VyLmluZm8oJ1tNQ1BdIFJlZ2VuZXJhdGluZyBhdXRoZW50aWNhdGlvbiB0b2tlbicpO1xuICAgIHJldHVybiB0aGlzLmdlbmVyYXRlVG9rZW4oKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBWYWxpZGF0ZSBwcm92aWRlZCB0b2tlbiBhZ2FpbnN0IHN0b3JlZCB0b2tlblxuICAgKi9cbiAgdmFsaWRhdGVUb2tlbihwcm92aWRlZFRva2VuOiBzdHJpbmcgfCB1bmRlZmluZWQpOiBib29sZWFuIHtcbiAgICBpZiAoIXRoaXMudG9rZW4gfHwgIXByb3ZpZGVkVG9rZW4pIHtcbiAgICAgIHRoaXMubG9nZ2VyLndhcm4oXG4gICAgICAgIGBbTUNQIEF1dGhdIFZhbGlkYXRpb24gZmFpbGVkOiB0b2tlbj0keyEhdGhpcy50b2tlbn0sIHByb3ZpZGVkPSR7ISFwcm92aWRlZFRva2VufWBcbiAgICAgICk7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgLy8gU3VwcG9ydCBib3RoIHJhdyB0b2tlbiBhbmQgQmVhcmVyIHByZWZpeFxuICAgIGNvbnN0IHJhd1Rva2VuID0gcHJvdmlkZWRUb2tlbi5zdGFydHNXaXRoKCdCZWFyZXIgJykgPyBwcm92aWRlZFRva2VuLnNsaWNlKDcpIDogcHJvdmlkZWRUb2tlbjtcblxuICAgIGNvbnN0IGlzVmFsaWQgPSByYXdUb2tlbiA9PT0gdGhpcy50b2tlbjtcbiAgICBpZiAoIWlzVmFsaWQpIHtcbiAgICAgIHRoaXMubG9nZ2VyLndhcm4oXG4gICAgICAgIGBbTUNQIEF1dGhdIFRva2VuIG1pc21hdGNoOiBwcm92aWRlZD0ke3Jhd1Rva2VuLnN1YnN0cmluZygwLCAyMCl9Li4uIHN0b3JlZD0ke3RoaXMudG9rZW4uc3Vic3RyaW5nKDAsIDIwKX0uLi5gXG4gICAgICApO1xuICAgIH1cbiAgICByZXR1cm4gaXNWYWxpZDtcbiAgfVxuXG4gIC8qKlxuICAgKiBWYWxpZGF0ZSB0aGF0IHJlcXVlc3QgY29tZXMgZnJvbSB0cnVzdGVkIElQXG4gICAqL1xuICB2YWxpZGF0ZUlQKGlwOiBzdHJpbmcgfCB1bmRlZmluZWQpOiBib29sZWFuIHtcbiAgICBpZiAoIWlwKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICAgIHJldHVybiAoVFJVU1RFRF9JUFMgYXMgcmVhZG9ubHkgc3RyaW5nW10pLmluY2x1ZGVzKGlwKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBFeHRyYWN0IEJlYXJlciB0b2tlbiBmcm9tIEF1dGhvcml6YXRpb24gaGVhZGVyXG4gICAqL1xuICBleHRyYWN0QmVhcmVyVG9rZW4oYXV0aEhlYWRlcjogc3RyaW5nIHwgdW5kZWZpbmVkKTogc3RyaW5nIHwgdW5kZWZpbmVkIHtcbiAgICBpZiAoIWF1dGhIZWFkZXIpIHtcbiAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgfVxuXG4gICAgaWYgKGF1dGhIZWFkZXIuc3RhcnRzV2l0aCgnQmVhcmVyICcpKSB7XG4gICAgICByZXR1cm4gYXV0aEhlYWRlci5zbGljZSg3KTtcbiAgICB9XG5cbiAgICByZXR1cm4gYXV0aEhlYWRlcjtcbiAgfVxufVxuIl19
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP Server
|
|
3
|
+
* Main server class that handles HTTP/SSE connections for MCP protocol
|
|
4
|
+
*/
|
|
5
|
+
import { McpConnectionInfo, McpServerConfig, McpServerStatus, LocalServices } from '../../common/types';
|
|
6
|
+
export declare class McpServer {
|
|
7
|
+
private server;
|
|
8
|
+
private port;
|
|
9
|
+
private auth;
|
|
10
|
+
private connectionInfo;
|
|
11
|
+
private services;
|
|
12
|
+
private logger;
|
|
13
|
+
private startTime;
|
|
14
|
+
constructor(config: McpServerConfig, services: LocalServices, logger: any);
|
|
15
|
+
/**
|
|
16
|
+
* Start the MCP server
|
|
17
|
+
*/
|
|
18
|
+
start(): Promise<void>;
|
|
19
|
+
/**
|
|
20
|
+
* Stop the MCP server
|
|
21
|
+
*/
|
|
22
|
+
stop(): Promise<void>;
|
|
23
|
+
/**
|
|
24
|
+
* Check if server is running
|
|
25
|
+
*/
|
|
26
|
+
isRunning(): boolean;
|
|
27
|
+
/**
|
|
28
|
+
* Get server status
|
|
29
|
+
*/
|
|
30
|
+
getStatus(): McpServerStatus;
|
|
31
|
+
/**
|
|
32
|
+
* Get connection info for external tools
|
|
33
|
+
*/
|
|
34
|
+
getConnectionInfo(): McpConnectionInfo;
|
|
35
|
+
/**
|
|
36
|
+
* Regenerate the authentication token
|
|
37
|
+
*/
|
|
38
|
+
regenerateToken(): Promise<string>;
|
|
39
|
+
/**
|
|
40
|
+
* Find an available port starting from the preferred port
|
|
41
|
+
*/
|
|
42
|
+
private findAvailablePort;
|
|
43
|
+
/**
|
|
44
|
+
* Handle incoming HTTP requests
|
|
45
|
+
*/
|
|
46
|
+
private handleRequest;
|
|
47
|
+
/**
|
|
48
|
+
* Handle health check requests
|
|
49
|
+
*/
|
|
50
|
+
private handleHealth;
|
|
51
|
+
/**
|
|
52
|
+
* Handle SSE connection for MCP protocol
|
|
53
|
+
*/
|
|
54
|
+
private handleSSE;
|
|
55
|
+
/**
|
|
56
|
+
* Handle MCP message requests
|
|
57
|
+
*/
|
|
58
|
+
private handleMessage;
|
|
59
|
+
/**
|
|
60
|
+
* Process an MCP message and return response
|
|
61
|
+
*/
|
|
62
|
+
private processMessage;
|
|
63
|
+
/**
|
|
64
|
+
* Send an error response
|
|
65
|
+
*/
|
|
66
|
+
private sendError;
|
|
67
|
+
}
|
|
@@ -0,0 +1,343 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* MCP Server
|
|
4
|
+
* Main server class that handles HTTP/SSE connections for MCP protocol
|
|
5
|
+
*/
|
|
6
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
7
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
8
|
+
};
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.McpServer = void 0;
|
|
11
|
+
const http_1 = __importDefault(require("http"));
|
|
12
|
+
const url_1 = require("url");
|
|
13
|
+
const constants_1 = require("../../common/constants");
|
|
14
|
+
const McpAuth_1 = require("./McpAuth");
|
|
15
|
+
const ConnectionInfo_1 = require("../config/ConnectionInfo");
|
|
16
|
+
const tools_1 = require("./tools");
|
|
17
|
+
class McpServer {
|
|
18
|
+
constructor(config, services, logger) {
|
|
19
|
+
this.server = null;
|
|
20
|
+
this.startTime = 0;
|
|
21
|
+
this.port = config.port || constants_1.MCP_SERVER.DEFAULT_PORT;
|
|
22
|
+
this.services = services;
|
|
23
|
+
this.logger = logger;
|
|
24
|
+
this.auth = new McpAuth_1.McpAuth(logger);
|
|
25
|
+
this.connectionInfo = new ConnectionInfo_1.ConnectionInfoManager(logger);
|
|
26
|
+
// Set token if provided
|
|
27
|
+
if (config.authToken) {
|
|
28
|
+
this.auth.setToken(config.authToken);
|
|
29
|
+
}
|
|
30
|
+
// Register all tools
|
|
31
|
+
(0, tools_1.registerTools)();
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Start the MCP server
|
|
35
|
+
*/
|
|
36
|
+
async start() {
|
|
37
|
+
if (this.server) {
|
|
38
|
+
this.logger.warn('[MCP] Server already running');
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
// Try to load existing token from connection info (for persistence across restarts)
|
|
42
|
+
const existingInfo = await this.connectionInfo.load();
|
|
43
|
+
if (existingInfo?.authToken) {
|
|
44
|
+
this.auth.setToken(existingInfo.authToken);
|
|
45
|
+
this.logger.info(`[MCP] Loaded existing auth token: ${existingInfo.authToken.substring(0, 20)}...`);
|
|
46
|
+
}
|
|
47
|
+
// Find available port
|
|
48
|
+
this.port = await this.findAvailablePort(this.port);
|
|
49
|
+
return new Promise((resolve, reject) => {
|
|
50
|
+
this.server = http_1.default.createServer((req, res) => this.handleRequest(req, res));
|
|
51
|
+
this.server.on('error', (err) => {
|
|
52
|
+
if (err.code === 'EADDRINUSE') {
|
|
53
|
+
this.logger.error(`[MCP] Port ${this.port} is in use`);
|
|
54
|
+
reject(new Error(`Port ${this.port} is already in use`));
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
this.logger.error('[MCP] Server error:', err);
|
|
58
|
+
reject(err);
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
this.server.listen(this.port, '127.0.0.1', async () => {
|
|
62
|
+
this.startTime = Date.now();
|
|
63
|
+
this.logger.info(`[MCP] Server started on http://127.0.0.1:${this.port}`);
|
|
64
|
+
// Save connection info
|
|
65
|
+
const info = this.getConnectionInfo();
|
|
66
|
+
await this.connectionInfo.save(info);
|
|
67
|
+
resolve();
|
|
68
|
+
});
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Stop the MCP server
|
|
73
|
+
*/
|
|
74
|
+
async stop() {
|
|
75
|
+
if (!this.server) {
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
return new Promise((resolve) => {
|
|
79
|
+
this.server.close(() => {
|
|
80
|
+
this.logger.info('[MCP] Server stopped');
|
|
81
|
+
this.server = null;
|
|
82
|
+
this.connectionInfo.delete();
|
|
83
|
+
resolve();
|
|
84
|
+
});
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Check if server is running
|
|
89
|
+
*/
|
|
90
|
+
isRunning() {
|
|
91
|
+
return this.server !== null;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Get server status
|
|
95
|
+
*/
|
|
96
|
+
getStatus() {
|
|
97
|
+
return {
|
|
98
|
+
running: this.isRunning(),
|
|
99
|
+
port: this.port,
|
|
100
|
+
uptime: this.isRunning() ? (Date.now() - this.startTime) / 1000 : 0,
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Get connection info for external tools
|
|
105
|
+
*/
|
|
106
|
+
getConnectionInfo() {
|
|
107
|
+
return {
|
|
108
|
+
url: `http://127.0.0.1:${this.port}`,
|
|
109
|
+
authToken: this.auth.getToken(),
|
|
110
|
+
port: this.port,
|
|
111
|
+
version: constants_1.MCP_SERVER.VERSION,
|
|
112
|
+
tools: (0, tools_1.getToolNames)(),
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Regenerate the authentication token
|
|
117
|
+
*/
|
|
118
|
+
async regenerateToken() {
|
|
119
|
+
const newToken = this.auth.regenerateToken();
|
|
120
|
+
// Update connection info file with new token
|
|
121
|
+
const info = this.getConnectionInfo();
|
|
122
|
+
await this.connectionInfo.save(info);
|
|
123
|
+
this.logger.info(`[MCP] Auth token regenerated`);
|
|
124
|
+
return newToken;
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Find an available port starting from the preferred port
|
|
128
|
+
*/
|
|
129
|
+
async findAvailablePort(preferredPort) {
|
|
130
|
+
const isPortAvailable = (port) => {
|
|
131
|
+
return new Promise((resolve) => {
|
|
132
|
+
const testServer = http_1.default.createServer();
|
|
133
|
+
testServer.once('error', () => resolve(false));
|
|
134
|
+
testServer.once('listening', () => {
|
|
135
|
+
testServer.close(() => resolve(true));
|
|
136
|
+
});
|
|
137
|
+
testServer.listen(port, '127.0.0.1');
|
|
138
|
+
});
|
|
139
|
+
};
|
|
140
|
+
for (let port = preferredPort; port <= constants_1.MCP_SERVER.PORT_RANGE.MAX; port++) {
|
|
141
|
+
if (await isPortAvailable(port)) {
|
|
142
|
+
if (port !== preferredPort) {
|
|
143
|
+
this.logger.info(`[MCP] Port ${preferredPort} unavailable, using ${port}`);
|
|
144
|
+
}
|
|
145
|
+
return port;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
throw new Error(`No available ports in range ${constants_1.MCP_SERVER.PORT_RANGE.MIN}-${constants_1.MCP_SERVER.PORT_RANGE.MAX}`);
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Handle incoming HTTP requests
|
|
152
|
+
*/
|
|
153
|
+
async handleRequest(req, res) {
|
|
154
|
+
const url = new url_1.URL(req.url || '/', `http://127.0.0.1:${this.port}`);
|
|
155
|
+
const pathname = url.pathname;
|
|
156
|
+
// IP check
|
|
157
|
+
if (!this.auth.validateIP(req.socket.remoteAddress)) {
|
|
158
|
+
this.sendError(res, 403, 'Forbidden: Only localhost connections allowed');
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
// Health endpoint (no auth required)
|
|
162
|
+
if (pathname === constants_1.MCP_ENDPOINTS.HEALTH) {
|
|
163
|
+
this.handleHealth(req, res);
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
// Auth check for all other endpoints
|
|
167
|
+
const authHeader = req.headers.authorization;
|
|
168
|
+
if (!this.auth.validateToken(authHeader)) {
|
|
169
|
+
this.sendError(res, 401, 'Unauthorized: Invalid or missing authentication token');
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
172
|
+
// Handle CORS preflight
|
|
173
|
+
if (req.method === 'OPTIONS') {
|
|
174
|
+
res.writeHead(200, {
|
|
175
|
+
'Access-Control-Allow-Origin': '*',
|
|
176
|
+
'Access-Control-Allow-Methods': 'GET, POST, OPTIONS',
|
|
177
|
+
'Access-Control-Allow-Headers': 'Content-Type, Authorization',
|
|
178
|
+
'Access-Control-Max-Age': '86400',
|
|
179
|
+
});
|
|
180
|
+
res.end();
|
|
181
|
+
return;
|
|
182
|
+
}
|
|
183
|
+
// Route to appropriate handler
|
|
184
|
+
if (pathname === constants_1.MCP_ENDPOINTS.SSE && req.method === 'GET') {
|
|
185
|
+
this.handleSSE(req, res);
|
|
186
|
+
}
|
|
187
|
+
else if (pathname === constants_1.MCP_ENDPOINTS.MESSAGES && req.method === 'POST') {
|
|
188
|
+
await this.handleMessage(req, res);
|
|
189
|
+
}
|
|
190
|
+
else {
|
|
191
|
+
this.sendError(res, 404, 'Not Found');
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Handle health check requests
|
|
196
|
+
*/
|
|
197
|
+
handleHealth(req, res) {
|
|
198
|
+
const status = this.getStatus();
|
|
199
|
+
const token = this.auth.getToken();
|
|
200
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
201
|
+
res.end(JSON.stringify({
|
|
202
|
+
status: 'ok',
|
|
203
|
+
version: constants_1.MCP_SERVER.VERSION,
|
|
204
|
+
uptime: status.uptime,
|
|
205
|
+
tools: (0, tools_1.getToolNames)(),
|
|
206
|
+
tokenPrefix: token.substring(0, 20),
|
|
207
|
+
}));
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* Handle SSE connection for MCP protocol
|
|
211
|
+
*/
|
|
212
|
+
handleSSE(req, res) {
|
|
213
|
+
res.writeHead(200, {
|
|
214
|
+
'Content-Type': 'text/event-stream',
|
|
215
|
+
'Cache-Control': 'no-cache',
|
|
216
|
+
Connection: 'keep-alive',
|
|
217
|
+
'Access-Control-Allow-Origin': '*',
|
|
218
|
+
});
|
|
219
|
+
// Send endpoint information
|
|
220
|
+
const messagesUrl = `http://127.0.0.1:${this.port}${constants_1.MCP_ENDPOINTS.MESSAGES}`;
|
|
221
|
+
res.write(`event: endpoint\ndata: ${messagesUrl}\n\n`);
|
|
222
|
+
// Keep connection alive
|
|
223
|
+
const keepAlive = setInterval(() => {
|
|
224
|
+
res.write(': keepalive\n\n');
|
|
225
|
+
}, 30000);
|
|
226
|
+
req.on('close', () => {
|
|
227
|
+
clearInterval(keepAlive);
|
|
228
|
+
});
|
|
229
|
+
}
|
|
230
|
+
/**
|
|
231
|
+
* Handle MCP message requests
|
|
232
|
+
*/
|
|
233
|
+
async handleMessage(req, res) {
|
|
234
|
+
let body = '';
|
|
235
|
+
req.on('data', (chunk) => {
|
|
236
|
+
body += chunk;
|
|
237
|
+
});
|
|
238
|
+
req.on('end', async () => {
|
|
239
|
+
try {
|
|
240
|
+
const request = JSON.parse(body);
|
|
241
|
+
// Notifications don't have an id and don't expect a response
|
|
242
|
+
if (request.method?.startsWith('notifications/')) {
|
|
243
|
+
this.logger.info(`[MCP] Received notification: ${request.method}`);
|
|
244
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
245
|
+
res.end('{}');
|
|
246
|
+
return;
|
|
247
|
+
}
|
|
248
|
+
const response = await this.processMessage(request);
|
|
249
|
+
res.writeHead(200, {
|
|
250
|
+
'Content-Type': 'application/json',
|
|
251
|
+
'Access-Control-Allow-Origin': '*',
|
|
252
|
+
});
|
|
253
|
+
res.end(JSON.stringify(response));
|
|
254
|
+
}
|
|
255
|
+
catch (error) {
|
|
256
|
+
this.logger.error('[MCP] Message handling error:', error);
|
|
257
|
+
this.sendError(res, 400, `Invalid request: ${error.message}`);
|
|
258
|
+
}
|
|
259
|
+
});
|
|
260
|
+
}
|
|
261
|
+
/**
|
|
262
|
+
* Process an MCP message and return response
|
|
263
|
+
*/
|
|
264
|
+
async processMessage(request) {
|
|
265
|
+
const { id, method, params } = request;
|
|
266
|
+
switch (method) {
|
|
267
|
+
case 'initialize':
|
|
268
|
+
return {
|
|
269
|
+
jsonrpc: '2.0',
|
|
270
|
+
id,
|
|
271
|
+
result: {
|
|
272
|
+
protocolVersion: '2024-11-05',
|
|
273
|
+
capabilities: {
|
|
274
|
+
tools: {},
|
|
275
|
+
},
|
|
276
|
+
serverInfo: {
|
|
277
|
+
name: constants_1.MCP_SERVER.NAME,
|
|
278
|
+
version: constants_1.MCP_SERVER.VERSION,
|
|
279
|
+
},
|
|
280
|
+
},
|
|
281
|
+
};
|
|
282
|
+
case 'tools/list':
|
|
283
|
+
return {
|
|
284
|
+
jsonrpc: '2.0',
|
|
285
|
+
id,
|
|
286
|
+
result: {
|
|
287
|
+
tools: (0, tools_1.getToolDefinitions)(),
|
|
288
|
+
},
|
|
289
|
+
};
|
|
290
|
+
case 'tools/call':
|
|
291
|
+
if (!params?.name) {
|
|
292
|
+
return {
|
|
293
|
+
jsonrpc: '2.0',
|
|
294
|
+
id,
|
|
295
|
+
error: {
|
|
296
|
+
code: -32602,
|
|
297
|
+
message: 'Missing tool name',
|
|
298
|
+
},
|
|
299
|
+
};
|
|
300
|
+
}
|
|
301
|
+
if (!(0, tools_1.hasTool)(params.name)) {
|
|
302
|
+
return {
|
|
303
|
+
jsonrpc: '2.0',
|
|
304
|
+
id,
|
|
305
|
+
error: {
|
|
306
|
+
code: -32602,
|
|
307
|
+
message: `Unknown tool: ${params.name}`,
|
|
308
|
+
},
|
|
309
|
+
};
|
|
310
|
+
}
|
|
311
|
+
const result = await (0, tools_1.executeTool)(params.name, params.arguments || {}, this.services);
|
|
312
|
+
return {
|
|
313
|
+
jsonrpc: '2.0',
|
|
314
|
+
id,
|
|
315
|
+
result,
|
|
316
|
+
};
|
|
317
|
+
case 'ping':
|
|
318
|
+
return {
|
|
319
|
+
jsonrpc: '2.0',
|
|
320
|
+
id,
|
|
321
|
+
result: {},
|
|
322
|
+
};
|
|
323
|
+
default:
|
|
324
|
+
return {
|
|
325
|
+
jsonrpc: '2.0',
|
|
326
|
+
id,
|
|
327
|
+
error: {
|
|
328
|
+
code: -32601,
|
|
329
|
+
message: `Unknown method: ${method}`,
|
|
330
|
+
},
|
|
331
|
+
};
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
/**
|
|
335
|
+
* Send an error response
|
|
336
|
+
*/
|
|
337
|
+
sendError(res, statusCode, message) {
|
|
338
|
+
res.writeHead(statusCode, { 'Content-Type': 'application/json' });
|
|
339
|
+
res.end(JSON.stringify({ error: message }));
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
exports.McpServer = McpServer;
|
|
343
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiTWNwU2VydmVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL21haW4vbWNwL01jcFNlcnZlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUE7OztHQUdHOzs7Ozs7QUFFSCxnREFBd0I7QUFDeEIsNkJBQTBCO0FBQzFCLHNEQUFtRTtBQVNuRSx1Q0FBb0M7QUFDcEMsNkRBQWlFO0FBQ2pFLG1DQUFnRztBQUVoRyxNQUFhLFNBQVM7SUFTcEIsWUFBWSxNQUF1QixFQUFFLFFBQXVCLEVBQUUsTUFBVztRQVJqRSxXQUFNLEdBQXVCLElBQUksQ0FBQztRQU1sQyxjQUFTLEdBQVcsQ0FBQyxDQUFDO1FBRzVCLElBQUksQ0FBQyxJQUFJLEdBQUcsTUFBTSxDQUFDLElBQUksSUFBSSxzQkFBVSxDQUFDLFlBQVksQ0FBQztRQUNuRCxJQUFJLENBQUMsUUFBUSxHQUFHLFFBQVEsQ0FBQztRQUN6QixJQUFJLENBQUMsTUFBTSxHQUFHLE1BQU0sQ0FBQztRQUNyQixJQUFJLENBQUMsSUFBSSxHQUFHLElBQUksaUJBQU8sQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUNoQyxJQUFJLENBQUMsY0FBYyxHQUFHLElBQUksc0NBQXFCLENBQUMsTUFBTSxDQUFDLENBQUM7UUFFeEQsd0JBQXdCO1FBQ3hCLElBQUksTUFBTSxDQUFDLFNBQVMsRUFBRSxDQUFDO1lBQ3JCLElBQUksQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLE1BQU0sQ0FBQyxTQUFTLENBQUMsQ0FBQztRQUN2QyxDQUFDO1FBRUQscUJBQXFCO1FBQ3JCLElBQUEscUJBQWEsR0FBRSxDQUFDO0lBQ2xCLENBQUM7SUFFRDs7T0FFRztJQUNILEtBQUssQ0FBQyxLQUFLO1FBQ1QsSUFBSSxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUM7WUFDaEIsSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsOEJBQThCLENBQUMsQ0FBQztZQUNqRCxPQUFPO1FBQ1QsQ0FBQztRQUVELG9GQUFv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Q0YsTUFBTSxFQUFFLEVBQUU7aUJBQ1gsQ0FBQztZQUVKO2dCQUNFLE9BQU87b0JBQ0wsT0FBTyxFQUFFLEtBQUs7b0JBQ2QsRUFBRTtvQkFDRixLQUFLLEVBQUU7d0JBQ0wsSUFBSSxFQUFFLENBQUMsS0FBSzt3QkFDWixPQUFPLEVBQUUsbUJBQW1CLE1BQU0sRUFBRTtxQkFDckM7aUJBQ0YsQ0FBQztRQUNOLENBQUM7SUFDSCxDQUFDO0lBRUQ7O09BRUc7SUFDSyxTQUFTLENBQUMsR0FBd0IsRUFBRSxVQUFrQixFQUFFLE9BQWU7UUFDN0UsR0FBRyxDQUFDLFNBQVMsQ0FBQyxVQUFVLEVBQUUsRUFBRSxjQUFjLEVBQUUsa0JBQWtCLEVBQUUsQ0FBQyxDQUFDO1FBQ2xFLEdBQUcsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxFQUFFLEtBQUssRUFBRSxPQUFPLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDOUMsQ0FBQztDQUNGO0FBMVhELDhCQTBYQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogTUNQIFNlcnZlclxuICogTWFpbiBzZXJ2ZXIgY2xhc3MgdGhhdCBoYW5kbGVzIEhUVFAvU1NFIGNvbm5lY3Rpb25zIGZvciBNQ1AgcHJvdG9jb2xcbiAqL1xuXG5pbXBvcnQgaHR0cCBmcm9tICdodHRwJztcbmltcG9ydCB7IFVSTCB9IGZyb20gJ3VybCc7XG5pbXBvcnQgeyBNQ1BfU0VSVkVSLCBNQ1BfRU5EUE9JTlRTIH0gZnJvbSAnLi4vLi4vY29tbW9uL2NvbnN0YW50cyc7XG5pbXBvcnQge1xuICBNY3BDb25uZWN0aW9uSW5mbyxcbiAgTWNwU2VydmVyQ29uZmlnLFxuICBNY3BTZXJ2ZXJTdGF0dXMsXG4gIE1jcFJlcXVlc3QsXG4gIE1jcFJlc3BvbnNlLFxuICBMb2NhbFNlcnZpY2VzLFxufSBmcm9tICcuLi8uLi9jb21tb24vdHlwZXMnO1xuaW1wb3J0IHsgTWNwQXV0aCB9IGZyb20gJy4vTWNwQXV0aCc7XG5pbXBvcnQgeyBDb25uZWN0aW9uSW5mb01hbmFnZXIgfSBmcm9tICcuLi9jb25maWcvQ29ubmVjdGlvbkluZm8nO1xuaW1wb3J0IHsgcmVnaXN0ZXJUb29scywgZ2V0VG9vbERlZmluaXRpb25zLCBnZXRUb29sTmFtZXMsIGV4ZWN1dGVUb29sLCBoYXNUb29sIH0gZnJvbSAnLi90b29scyc7XG5cbmV4cG9ydCBjbGFzcyBNY3BTZXJ2ZXIge1xuICBwcml2YXRlIHNlcnZlcjogaHR0cC5TZXJ2ZXIgfCBudWxsID0gbnVsbDtcbiAgcHJpdmF0ZSBwb3J0OiBudW1iZXI7XG4gIHByaXZhdGUgYXV0aDogTWNwQXV0aDtcbiAgcHJpdmF0ZSBjb25uZWN0aW9uSW5mbzogQ29ubmVjdGlvbkluZm9NYW5hZ2VyO1xuICBwcml2YXRlIHNlcnZpY2VzOiBMb2NhbFNlcnZpY2VzO1xuICBwcml2YXRlIGxvZ2dlcjogYW55O1xuICBwcml2YXRlIHN0YXJ0VGltZTogbnVtYmVyID0gMDtcblxuICBjb25zdHJ1Y3Rvcihjb25maWc6IE1jcFNlcnZlckNvbmZpZywgc2VydmljZXM6IExvY2FsU2VydmljZXMsIGxvZ2dlcjogYW55KSB7XG4gICAgdGhpcy5wb3J0ID0gY29uZmlnLnBvcnQgfHwgTUNQX1NFUlZFUi5ERUZBVUxUX1BPUlQ7XG4gICAgdGhpcy5zZXJ2aWNlcyA9IHNlcnZpY2VzO1xuICAgIHRoaXMubG9nZ2VyID0gbG9nZ2VyO1xuICAgIHRoaXMuYXV0aCA9IG5ldyBNY3BBdXRoKGxvZ2dlcik7XG4gICAgdGhpcy5jb25uZWN0aW9uSW5mbyA9IG5ldyBDb25uZWN0aW9uSW5mb01hbmFnZXIobG9nZ2VyKTtcblxuICAgIC8vIFNldCB0b2tlbiBpZiBwcm92aWRlZFxuICAgIGlmIChjb25maWcuYXV0aFRva2VuKSB7XG4gICAgICB0aGlzLmF1dGguc2V0VG9rZW4oY29uZmlnLmF1dGhUb2tlbik7XG4gICAgfVxuXG4gICAgLy8gUmVnaXN0ZXIgYWxsIHRvb2xzXG4gICAgcmVnaXN0ZXJUb29scygpO1xuICB9XG5cbiAgLyoqXG4gICAqIFN0YXJ0IHRoZSBNQ1Agc2VydmVyXG4gICAqL1xuICBhc3luYyBzdGFydCgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBpZiAodGhpcy5zZXJ2ZXIpIHtcbiAgICAgIHRoaXMubG9nZ2VyLndhcm4oJ1tNQ1BdIFNlcnZlciBhbHJlYWR5IHJ1bm5pbmcnKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICAvLyBUcnkgdG8gbG9hZCBleGlzdGluZyB0b2tlbiBmcm9tIGNvbm5lY3Rpb24gaW5mbyAoZm9yIHBlcnNpc3RlbmNlIGFjcm9zcyByZXN0YXJ0cylcbiAgICBjb25zdCBleGlzdGluZ0luZm8gPSBhd2FpdCB0aGlzLmNvbm5lY3Rpb25JbmZvLmxvYWQoKTtcbiAgICBpZiAoZXhpc3RpbmdJbmZvPy5hdXRoVG9rZW4pIHtcbiAgICAgIHRoaXMuYXV0aC5zZXRUb2tlbihleGlzdGluZ0luZm8uYXV0aFRva2VuKTtcbiAgICAgIHRoaXMubG9nZ2VyLmluZm8oXG4gICAgICAgIGBbTUNQXSBMb2FkZWQgZXhpc3RpbmcgYXV0aCB0b2tlbjogJHtleGlzdGluZ0luZm8uYXV0aFRva2VuLnN1YnN0cmluZygwLCAyMCl9Li4uYFxuICAgICAgKTtcbiAgICB9XG5cbiAgICAvLyBGaW5kIGF2YWlsYWJsZSBwb3J0XG4gICAgdGhpcy5wb3J0ID0gYXdhaXQgdGhpcy5maW5kQXZhaWxhYmxlUG9ydCh0aGlzLnBvcnQpO1xuXG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgIHRoaXMuc2VydmVyID0gaHR0cC5jcmVhdGVTZXJ2ZXIoKHJlcSwgcmVzKSA9PiB0aGlzLmhhbmRsZVJlcXVlc3QocmVxLCByZXMpKTtcblxuICAgICAgdGhpcy5zZXJ2ZXIub24oJ2Vycm9yJywgKGVycjogYW55KSA9PiB7XG4gICAgICAgIGlmIChlcnIuY29kZSA9PT0gJ0VBRERSSU5VU0UnKSB7XG4gICAgICAgICAgdGhpcy5sb2dnZXIuZXJyb3IoYFtNQ1BdIFBvcnQgJHt0aGlzLnBvcnR9IGlzIGluIHVzZWApO1xuICAgICAgICAgIHJlamVjdChuZXcgRXJyb3IoYFBvcnQgJHt0aGlzLnBvcnR9IGlzIGFscmVhZHkgaW4gdXNlYCkpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHRoaXMubG9nZ2VyLmVycm9yKCdbTUNQXSBTZXJ2ZXIgZXJyb3I6JywgZXJyKTtcbiAgICAgICAgICByZWplY3QoZXJyKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG5cbiAgICAgIHRoaXMuc2VydmVyLmxpc3Rlbih0aGlzLnBvcnQsICcxMjcuMC4wLjEnLCBhc3luYyAoKSA9PiB7XG4gICAgICAgIHRoaXMuc3RhcnRUaW1lID0gRGF0ZS5ub3coKTtcbiAgICAgICAgdGhpcy5sb2dnZXIuaW5mbyhgW01DUF0gU2VydmVyIHN0YXJ0ZWQgb24gaHR0cDovLzEyNy4wLjAuMToke3RoaXMucG9ydH1gKTtcblxuICAgICAgICAvLyBTYXZlIGNvbm5lY3Rpb24gaW5mb1xuICAgICAgICBjb25zdCBpbmZvID0gdGhpcy5nZXRDb25uZWN0aW9uSW5mbygpO1xuICAgICAgICBhd2FpdCB0aGlzLmNvbm5lY3Rpb25JbmZvLnNhdmUoaW5mbyk7XG5cbiAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgfSk7XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogU3RvcCB0aGUgTUNQIHNlcnZlclxuICAgKi9cbiAgYXN5bmMgc3RvcCgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBpZiAoIXRoaXMuc2VydmVyKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlKSA9PiB7XG4gICAgICB0aGlzLnNlcnZlciEuY2xvc2UoKCkgPT4ge1xuICAgICAgICB0aGlzLmxvZ2dlci5pbmZvKCdbTUNQXSBTZXJ2ZXIgc3RvcHBlZCcpO1xuICAgICAgICB0aGlzLnNlcnZlciA9IG51bGw7XG4gICAgICAgIHRoaXMuY29ubmVjdGlvbkluZm8uZGVsZXRlKCk7XG4gICAgICAgIHJlc29sdmUoKTtcbiAgICAgIH0pO1xuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIENoZWNrIGlmIHNlcnZlciBpcyBydW5uaW5nXG4gICAqL1xuICBpc1J1bm5pbmcoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMuc2VydmVyICE9PSBudWxsO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldCBzZXJ2ZXIgc3RhdHVzXG4gICAqL1xuICBnZXRTdGF0dXMoKTogTWNwU2VydmVyU3RhdHVzIHtcbiAgICByZXR1cm4ge1xuICAgICAgcnVubmluZzogdGhpcy5pc1J1bm5pbmcoKSxcbiAgICAgIHBvcnQ6IHRoaXMucG9ydCxcbiAgICAgIHVwdGltZTogdGhpcy5pc1J1bm5pbmcoKSA/IChEYXRlLm5vdygpIC0gdGhpcy5zdGFydFRpbWUpIC8gMTAwMCA6IDAsXG4gICAgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXQgY29ubmVjdGlvbiBpbmZvIGZvciBleHRlcm5hbCB0b29sc1xuICAgKi9cbiAgZ2V0Q29ubmVjdGlvbkluZm8oKTogTWNwQ29ubmVjdGlvbkluZm8ge1xuICAgIHJldHVybiB7XG4gICAgICB1cmw6IGBodHRwOi8vMTI3LjAuMC4xOiR7dGhpcy5wb3J0fWAsXG4gICAgICBhdXRoVG9rZW46IHRoaXMuYXV0aC5nZXRUb2tlbigpLFxuICAgICAgcG9ydDogdGhpcy5wb3J0LFxuICAgICAgdmVyc2lvbjogTUNQX1NFUlZFUi5WRVJTSU9OLFxuICAgICAgdG9vbHM6IGdldFRvb2xOYW1lcygpLFxuICAgIH07XG4gIH1cblxuICAvKipcbiAgICogUmVnZW5lcmF0ZSB0aGUgYXV0aGVudGljYXRpb24gdG9rZW5cbiAgICovXG4gIGFzeW5jIHJlZ2VuZXJhdGVUb2tlbigpOiBQcm9taXNlPHN0cmluZz4ge1xuICAgIGNvbnN0IG5ld1Rva2VuID0gdGhpcy5hdXRoLnJlZ2VuZXJhdGVUb2tlbigpO1xuICAgIC8vIFVwZGF0ZSBjb25uZWN0aW9uIGluZm8gZmlsZSB3aXRoIG5ldyB0b2tlblxuICAgIGNvbnN0IGluZm8gPSB0aGlzLmdldENvbm5lY3Rpb25JbmZvKCk7XG4gICAgYXdhaXQgdGhpcy5jb25uZWN0aW9uSW5mby5zYXZlKGluZm8pO1xuICAgIHRoaXMubG9nZ2VyLmluZm8oYFtNQ1BdIEF1dGggdG9rZW4gcmVnZW5lcmF0ZWRgKTtcbiAgICByZXR1cm4gbmV3VG9rZW47XG4gIH1cblxuICAvKipcbiAgICogRmluZCBhbiBhdmFpbGFibGUgcG9ydCBzdGFydGluZyBmcm9tIHRoZSBwcmVmZXJyZWQgcG9ydFxuICAgKi9cbiAgcHJpdmF0ZSBhc3luYyBmaW5kQXZhaWxhYmxlUG9ydChwcmVmZXJyZWRQb3J0OiBudW1iZXIpOiBQcm9taXNlPG51bWJlcj4ge1xuICAgIGNvbnN0IGlzUG9ydEF2YWlsYWJsZSA9IChwb3J0OiBudW1iZXIpOiBQcm9taXNlPGJvb2xlYW4+ID0+IHtcbiAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSkgPT4ge1xuICAgICAgICBjb25zdCB0ZXN0U2VydmVyID0gaHR0cC5jcmVhdGVTZXJ2ZXIoKTtcbiAgICAgICAgdGVzdFNlcnZlci5vbmNlKCdlcnJvcicsICgpID0+IHJlc29sdmUoZmFsc2UpKTtcbiAgICAgICAgdGVzdFNlcnZlci5vbmNlKCdsaXN0ZW5pbmcnLCAoKSA9PiB7XG4gICAgICAgICAgdGVzdFNlcnZlci5jbG9zZSgoKSA9PiByZXNvbHZlKHRydWUpKTtcbiAgICAgICAgfSk7XG4gICAgICAgIHRlc3RTZXJ2ZXIubGlzdGVuKHBvcnQsICcxMjcuMC4wLjEnKTtcbiAgICAgIH0pO1xuICAgIH07XG5cbiAgICBmb3IgKGxldCBwb3J0ID0gcHJlZmVycmVkUG9ydDsgcG9ydCA8PSBNQ1BfU0VSVkVSLlBPUlRfUkFOR0UuTUFYOyBwb3J0KyspIHtcbiAgICAgIGlmIChhd2FpdCBpc1BvcnRBdmFpbGFibGUocG9ydCkpIHtcbiAgICAgICAgaWYgKHBvcnQgIT09IHByZWZlcnJlZFBvcnQpIHtcbiAgICAgICAgICB0aGlzLmxvZ2dlci5pbmZvKGBbTUNQXSBQb3J0ICR7cHJlZmVycmVkUG9ydH0gdW5hdmFpbGFibGUsIHVzaW5nICR7cG9ydH1gKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcG9ydDtcbiAgICAgIH1cbiAgICB9XG5cbiAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICBgTm8gYXZhaWxhYmxlIHBvcnRzIGluIHJhbmdlICR7TUNQX1NFUlZFUi5QT1JUX1JBTkdFLk1JTn0tJHtNQ1BfU0VSVkVSLlBPUlRfUkFOR0UuTUFYfWBcbiAgICApO1xuICB9XG5cbiAgLyoqXG4gICAqIEhhbmRsZSBpbmNvbWluZyBIVFRQIHJlcXVlc3RzXG4gICAqL1xuICBwcml2YXRlIGFzeW5jIGhhbmRsZVJlcXVlc3QocmVxOiBodHRwLkluY29taW5nTWVzc2FnZSwgcmVzOiBodHRwLlNlcnZlclJlc3BvbnNlKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3QgdXJsID0gbmV3IFVSTChyZXEudXJsIHx8ICcvJywgYGh0dHA6Ly8xMjcuMC4wLjE6JHt0aGlzLnBvcnR9YCk7XG4gICAgY29uc3QgcGF0aG5hbWUgPSB1cmwucGF0aG5hbWU7XG5cbiAgICAvLyBJUCBjaGVja1xuICAgIGlmICghdGhpcy5hdXRoLnZhbGlkYXRlSVAocmVxLnNvY2tldC5yZW1vdGVBZGRyZXNzKSkge1xuICAgICAgdGhpcy5zZW5kRXJyb3IocmVzLCA0MDMsICdGb3JiaWRkZW46IE9ubHkgbG9jYWxob3N0IGNvbm5lY3Rpb25zIGFsbG93ZWQnKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICAvLyBIZWFsdGggZW5kcG9pbnQgKG5vIGF1dGggcmVxdWlyZWQpXG4gICAgaWYgKHBhdGhuYW1lID09PSBNQ1BfRU5EUE9JTlRTLkhFQUxUSCkge1xuICAgICAgdGhpcy5oYW5kbGVIZWFsdGgocmVxLCByZXMpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIC8vIEF1dGggY2hlY2sgZm9yIGFsbCBvdGhlciBlbmRwb2ludHNcbiAgICBjb25zdCBhdXRoSGVhZGVyID0gcmVxLmhlYWRlcnMuYXV0aG9yaXphdGlvbjtcbiAgICBpZiAoIXRoaXMuYXV0aC52YWxpZGF0ZVRva2VuKGF1dGhIZWFkZXIpKSB7XG4gICAgICB0aGlzLnNlbmRFcnJvcihyZXMsIDQwMSwgJ1VuYXV0aG9yaXplZDogSW52YWxpZCBvciBtaXNzaW5nIGF1dGhlbnRpY2F0aW9uIHRva2VuJyk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgLy8gSGFuZGxlIENPUlMgcHJlZmxpZ2h0XG4gICAgaWYgKHJlcS5tZXRob2QgPT09ICdPUFRJT05TJykge1xuICAgICAgcmVzLndyaXRlSGVhZCgyMDAsIHtcbiAgICAgICAgJ0FjY2Vzcy1Db250cm9sLUFsbG93LU9yaWdpbic6ICcqJyxcbiAgICAgICAgJ0FjY2Vzcy1Db250cm9sLUFsbG93LU1ldGhvZHMnOiAnR0VULCBQT1NULCBPUFRJT05TJyxcbiAgICAgICAgJ0FjY2Vzcy1Db250cm9sLUFsbG93LUhlYWRlcnMnOiAnQ29udGVudC1UeXBlLCBBdXRob3JpemF0aW9uJyxcbiAgICAgICAgJ0FjY2Vzcy1Db250cm9sLU1heC1BZ2UnOiAnODY0MDAnLFxuICAgICAgfSk7XG4gICAgICByZXMuZW5kKCk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgLy8gUm91dGUgdG8gYXBwcm9wcmlhdGUgaGFuZGxlclxuICAgIGlmIChwYXRobmFtZSA9PT0gTUNQX0VORFBPSU5UUy5TU0UgJiYgcmVxLm1ldGhvZCA9PT0gJ0dFVCcpIHtcbiAgICAgIHRoaXMuaGFuZGxlU1NFKHJlcSwgcmVzKTtcbiAgICB9IGVsc2UgaWYgKHBhdGhuYW1lID09PSBNQ1BfRU5EUE9JTlRTLk1FU1NBR0VTICYmIHJlcS5tZXRob2QgPT09ICdQT1NUJykge1xuICAgICAgYXdhaXQgdGhpcy5oYW5kbGVNZXNzYWdlKHJlcSwgcmVzKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5zZW5kRXJyb3IocmVzLCA0MDQsICdOb3QgRm91bmQnKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogSGFuZGxlIGhlYWx0aCBjaGVjayByZXF1ZXN0c1xuICAgKi9cbiAgcHJpdmF0ZSBoYW5kbGVIZWFsdGgocmVxOiBodHRwLkluY29taW5nTWVzc2FnZSwgcmVzOiBodHRwLlNlcnZlclJlc3BvbnNlKTogdm9pZCB7XG4gICAgY29uc3Qgc3RhdHVzID0gdGhpcy5nZXRTdGF0dXMoKTtcbiAgICBjb25zdCB0b2tlbiA9IHRoaXMuYXV0aC5nZXRUb2tlbigpO1xuICAgIHJlcy53cml0ZUhlYWQoMjAwLCB7ICdDb250ZW50LVR5cGUnOiAnYXBwbGljYXRpb24vanNvbicgfSk7XG4gICAgcmVzLmVuZChcbiAgICAgIEpTT04uc3RyaW5naWZ5KHtcbiAgICAgICAgc3RhdHVzOiAnb2snLFxuICAgICAgICB2ZXJzaW9uOiBNQ1BfU0VSVkVSLlZFUlNJT04sXG4gICAgICAgIHVwdGltZTogc3RhdHVzLnVwdGltZSxcbiAgICAgICAgdG9vbHM6IGdldFRvb2xOYW1lcygpLFxuICAgICAgICB0b2tlblByZWZpeDogdG9rZW4uc3Vic3RyaW5nKDAsIDIwKSxcbiAgICAgIH0pXG4gICAgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBIYW5kbGUgU1NFIGNvbm5lY3Rpb24gZm9yIE1DUCBwcm90b2NvbFxuICAgKi9cbiAgcHJpdmF0ZSBoYW5kbGVTU0UocmVxOiBodHRwLkluY29taW5nTWVzc2FnZSwgcmVzOiBodHRwLlNlcnZlclJlc3BvbnNlKTogdm9pZCB7XG4gICAgcmVzLndyaXRlSGVhZCgyMDAsIHtcbiAgICAgICdDb250ZW50LVR5cGUnOiAndGV4dC9ldmVudC1zdHJlYW0nLFxuICAgICAgJ0NhY2hlLUNvbnRyb2wnOiAnbm8tY2FjaGUnLFxuICAgICAgQ29ubmVjdGlvbjogJ2tlZXAtYWxpdmUnLFxuICAgICAgJ0FjY2Vzcy1Db250cm9sLUFsbG93LU9yaWdpbic6ICcqJyxcbiAgICB9KTtcblxuICAgIC8vIFNlbmQgZW5kcG9pbnQgaW5mb3JtYXRpb25cbiAgICBjb25zdCBtZXNzYWdlc1VybCA9IGBodHRwOi8vMTI3LjAuMC4xOiR7dGhpcy5wb3J0fSR7TUNQX0VORFBPSU5UUy5NRVNTQUdFU31gO1xuICAgIHJlcy53cml0ZShgZXZlbnQ6IGVuZHBvaW50XFxuZGF0YTogJHttZXNzYWdlc1VybH1cXG5cXG5gKTtcblxuICAgIC8vIEtlZXAgY29ubmVjdGlvbiBhbGl2ZVxuICAgIGNvbnN0IGtlZXBBbGl2ZSA9IHNldEludGVydmFsKCgpID0+IHtcbiAgICAgIHJlcy53cml0ZSgnOiBrZWVwYWxpdmVcXG5cXG4nKTtcbiAgICB9LCAzMDAwMCk7XG5cbiAgICByZXEub24oJ2Nsb3NlJywgKCkgPT4ge1xuICAgICAgY2xlYXJJbnRlcnZhbChrZWVwQWxpdmUpO1xuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIEhhbmRsZSBNQ1AgbWVzc2FnZSByZXF1ZXN0c1xuICAgKi9cbiAgcHJpdmF0ZSBhc3luYyBoYW5kbGVNZXNzYWdlKHJlcTogaHR0cC5JbmNvbWluZ01lc3NhZ2UsIHJlczogaHR0cC5TZXJ2ZXJSZXNwb25zZSk6IFByb21pc2U8dm9pZD4ge1xuICAgIGxldCBib2R5ID0gJyc7XG5cbiAgICByZXEub24oJ2RhdGEnLCAoY2h1bmspID0+IHtcbiAgICAgIGJvZHkgKz0gY2h1bms7XG4gICAgfSk7XG5cbiAgICByZXEub24oJ2VuZCcsIGFzeW5jICgpID0+IHtcbiAgICAgIHRyeSB7XG4gICAgICAgIGNvbnN0IHJlcXVlc3Q6IE1jcFJlcXVlc3QgPSBKU09OLnBhcnNlKGJvZHkpO1xuXG4gICAgICAgIC8vIE5vdGlmaWNhdGlvbnMgZG9uJ3QgaGF2ZSBhbiBpZCBhbmQgZG9uJ3QgZXhwZWN0IGEgcmVzcG9uc2VcbiAgICAgICAgaWYgKHJlcXVlc3QubWV0aG9kPy5zdGFydHNXaXRoKCdub3RpZmljYXRpb25zLycpKSB7XG4gICAgICAgICAgdGhpcy5sb2dnZXIuaW5mbyhgW01DUF0gUmVjZWl2ZWQgbm90aWZpY2F0aW9uOiAke3JlcXVlc3QubWV0aG9kfWApO1xuICAgICAgICAgIHJlcy53cml0ZUhlYWQoMjAwLCB7ICdDb250ZW50LVR5cGUnOiAnYXBwbGljYXRpb24vanNvbicgfSk7XG4gICAgICAgICAgcmVzLmVuZCgne30nKTtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMucHJvY2Vzc01lc3NhZ2UocmVxdWVzdCk7XG5cbiAgICAgICAgcmVzLndyaXRlSGVhZCgyMDAsIHtcbiAgICAgICAgICAnQ29udGVudC1UeXBlJzogJ2FwcGxpY2F0aW9uL2pzb24nLFxuICAgICAgICAgICdBY2Nlc3MtQ29udHJvbC1BbGxvdy1PcmlnaW4nOiAnKicsXG4gICAgICAgIH0pO1xuICAgICAgICByZXMuZW5kKEpTT04uc3RyaW5naWZ5KHJlc3BvbnNlKSk7XG4gICAgICB9IGNhdGNoIChlcnJvcjogYW55KSB7XG4gICAgICAgIHRoaXMubG9nZ2VyLmVycm9yKCdbTUNQXSBNZXNzYWdlIGhhbmRsaW5nIGVycm9yOicsIGVycm9yKTtcbiAgICAgICAgdGhpcy5zZW5kRXJyb3IocmVzLCA0MDAsIGBJbnZhbGlkIHJlcXVlc3Q6ICR7ZXJyb3IubWVzc2FnZX1gKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBQcm9jZXNzIGFuIE1DUCBtZXNzYWdlIGFuZCByZXR1cm4gcmVzcG9uc2VcbiAgICovXG4gIHByaXZhdGUgYXN5bmMgcHJvY2Vzc01lc3NhZ2UocmVxdWVzdDogTWNwUmVxdWVzdCk6IFByb21pc2U8TWNwUmVzcG9uc2U+IHtcbiAgICBjb25zdCB7IGlkLCBtZXRob2QsIHBhcmFtcyB9ID0gcmVxdWVzdDtcblxuICAgIHN3aXRjaCAobWV0aG9kKSB7XG4gICAgICBjYXNlICdpbml0aWFsaXplJzpcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICBqc29ucnBjOiAnMi4wJyxcbiAgICAgICAgICBpZCxcbiAgICAgICAgICByZXN1bHQ6IHtcbiAgICAgICAgICAgIHByb3RvY29sVmVyc2lvbjogJzIwMjQtMTEtMDUnLFxuICAgICAgICAgICAgY2FwYWJpbGl0aWVzOiB7XG4gICAgICAgICAgICAgIHRvb2xzOiB7fSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBzZXJ2ZXJJbmZvOiB7XG4gICAgICAgICAgICAgIG5hbWU6IE1DUF9TRVJWRVIuTkFNRSxcbiAgICAgICAgICAgICAgdmVyc2lvbjogTUNQX1NFUlZFUi5WRVJTSU9OLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICB9LFxuICAgICAgICB9O1xuXG4gICAgICBjYXNlICd0b29scy9saXN0JzpcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICBqc29ucnBjOiAnMi4wJyxcbiAgICAgICAgICBpZCxcbiAgICAgICAgICByZXN1bHQ6IHtcbiAgICAgICAgICAgIHRvb2xzOiBnZXRUb29sRGVmaW5pdGlvbnMoKSxcbiAgICAgICAgICB9LFxuICAgICAgICB9O1xuXG4gICAgICBjYXNlICd0b29scy9jYWxsJzpcbiAgICAgICAgaWYgKCFwYXJhbXM/Lm5hbWUpIHtcbiAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAganNvbnJwYzogJzIuMCcsXG4gICAgICAgICAgICBpZCxcbiAgICAgICAgICAgIGVycm9yOiB7XG4gICAgICAgICAgICAgIGNvZGU6IC0zMjYwMixcbiAgICAgICAgICAgICAgbWVzc2FnZTogJ01pc3NpbmcgdG9vbCBuYW1lJyxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgfTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghaGFzVG9vbChwYXJhbXMubmFtZSkpIHtcbiAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAganNvbnJwYzogJzIuMCcsXG4gICAgICAgICAgICBpZCxcbiAgICAgICAgICAgIGVycm9yOiB7XG4gICAgICAgICAgICAgIGNvZGU6IC0zMjYwMixcbiAgICAgICAgICAgICAgbWVzc2FnZTogYFVua25vd24gdG9vbDogJHtwYXJhbXMubmFtZX1gLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICB9O1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgZXhlY3V0ZVRvb2wocGFyYW1zLm5hbWUsIHBhcmFtcy5hcmd1bWVudHMgfHwge30sIHRoaXMuc2VydmljZXMpO1xuXG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAganNvbnJwYzogJzIuMCcsXG4gICAgICAgICAgaWQsXG4gICAgICAgICAgcmVzdWx0LFxuICAgICAgICB9O1xuXG4gICAgICBjYXNlICdwaW5nJzpcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICBqc29ucnBjOiAnMi4wJyxcbiAgICAgICAgICBpZCxcbiAgICAgICAgICByZXN1bHQ6IHt9LFxuICAgICAgICB9O1xuXG4gICAgICBkZWZhdWx0OlxuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIGpzb25ycGM6ICcyLjAnLFxuICAgICAgICAgIGlkLFxuICAgICAgICAgIGVycm9yOiB7XG4gICAgICAgICAgICBjb2RlOiAtMzI2MDEsXG4gICAgICAgICAgICBtZXNzYWdlOiBgVW5rbm93biBtZXRob2Q6ICR7bWV0aG9kfWAsXG4gICAgICAgICAgfSxcbiAgICAgICAgfTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogU2VuZCBhbiBlcnJvciByZXNwb25zZVxuICAgKi9cbiAgcHJpdmF0ZSBzZW5kRXJyb3IocmVzOiBodHRwLlNlcnZlclJlc3BvbnNlLCBzdGF0dXNDb2RlOiBudW1iZXIsIG1lc3NhZ2U6IHN0cmluZyk6IHZvaWQge1xuICAgIHJlcy53cml0ZUhlYWQoc3RhdHVzQ29kZSwgeyAnQ29udGVudC1UeXBlJzogJ2FwcGxpY2F0aW9uL2pzb24nIH0pO1xuICAgIHJlcy5lbmQoSlNPTi5zdHJpbmdpZnkoeyBlcnJvcjogbWVzc2FnZSB9KSk7XG4gIH1cbn1cbiJdfQ==
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* change_php_version Tool
|
|
3
|
+
* Change PHP version for a site
|
|
4
|
+
*/
|
|
5
|
+
import { McpToolDefinition, McpToolResult, LocalServices } from '../../../common/types';
|
|
6
|
+
export declare const changePhpVersionDefinition: McpToolDefinition;
|
|
7
|
+
export declare function changePhpVersion(args: Record<string, unknown>, services: LocalServices): Promise<McpToolResult>;
|