@sophia-vibelog/setup 0.1.2 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +33 -27
- package/dist/index.js.map +1 -1
- package/dist/steps/create-folder.d.ts.map +1 -1
- package/dist/steps/create-folder.js +6 -5
- package/dist/steps/create-folder.js.map +1 -1
- package/dist/steps/update-config.d.ts.map +1 -1
- package/dist/steps/update-config.js +7 -6
- package/dist/steps/update-config.js.map +1 -1
- package/dist/steps/verify-setup.d.ts.map +1 -1
- package/dist/steps/verify-setup.js +9 -8
- package/dist/steps/verify-setup.js.map +1 -1
- package/dist/utils/config.d.ts +11 -4
- package/dist/utils/config.d.ts.map +1 -1
- package/dist/utils/config.js +18 -3
- package/dist/utils/config.js.map +1 -1
- package/package.json +3 -2
- package/src/index.ts +48 -31
- package/src/steps/create-folder.ts +6 -5
- package/src/steps/update-config.ts +7 -6
- package/src/steps/verify-setup.ts +9 -8
- package/src/utils/config.ts +31 -6
package/dist/index.js
CHANGED
|
@@ -21,52 +21,58 @@ async function main() {
|
|
|
21
21
|
if (!apiKey) {
|
|
22
22
|
logger_1.logger.error("SOPHIA_API_KEY 환경변수가 설정되지 않았습니다");
|
|
23
23
|
logger_1.logger.info("\n사용 방법:");
|
|
24
|
-
logger_1.logger.info("SOPHIA_API_KEY=your_key npx @sophia-
|
|
24
|
+
logger_1.logger.info("SOPHIA_API_KEY=your_key npx @sophia-vibelog/setup");
|
|
25
25
|
process.exit(1);
|
|
26
26
|
}
|
|
27
27
|
const apiUrl = process.env.SOPHIA_API_URL || DEFAULT_API_URL;
|
|
28
28
|
const apiClient = new api_1.ApiClient(apiKey, apiUrl);
|
|
29
|
-
const
|
|
29
|
+
const managers = config_1.ConfigManager.createAll();
|
|
30
30
|
let installError;
|
|
31
31
|
try {
|
|
32
|
-
// Step 1: API 키 검증
|
|
32
|
+
// Step 1: API 키 검증 (한 번만)
|
|
33
33
|
const verifyResult = await (0, verify_key_1.verifyKey)(apiClient);
|
|
34
34
|
if (!verifyResult.success) {
|
|
35
35
|
installError = verifyResult.message;
|
|
36
36
|
throw new Error(verifyResult.message);
|
|
37
37
|
}
|
|
38
|
-
// Step 2:
|
|
39
|
-
const
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
38
|
+
// Step 2-4: 각 타겟(Claude Code, Cursor)에 설정
|
|
39
|
+
const results = [];
|
|
40
|
+
for (const manager of managers) {
|
|
41
|
+
console.log(chalk_1.default.cyan(`\n📦 ${manager.label} 설정 시작`));
|
|
42
|
+
// 폴더 생성
|
|
43
|
+
const folderResult = (0, create_folder_1.createFolder)(manager);
|
|
44
|
+
if (!folderResult.success) {
|
|
45
|
+
logger_1.logger.warn(`${manager.label} 폴더 생성 실패 — 건너뜁니다`);
|
|
46
|
+
continue;
|
|
47
|
+
}
|
|
48
|
+
// MCP 설정 추가
|
|
49
|
+
const configResult = (0, update_config_1.updateConfig)(manager, apiKey, apiUrl);
|
|
50
|
+
if (!configResult.success) {
|
|
51
|
+
logger_1.logger.warn(`${manager.label} 설정 추가 실패 — 건너뜁니다`);
|
|
52
|
+
continue;
|
|
53
|
+
}
|
|
54
|
+
// 설정 검증
|
|
55
|
+
const setupResult = (0, verify_setup_1.verifySetup)(manager);
|
|
56
|
+
if (!setupResult.success) {
|
|
57
|
+
logger_1.logger.warn(`${manager.label} 설정 검증 실패 — 건너뜁니다`);
|
|
58
|
+
continue;
|
|
59
|
+
}
|
|
60
|
+
results.push(manager.label);
|
|
43
61
|
}
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
installError = configResult.message;
|
|
48
|
-
throw configResult.error || new Error(configResult.message);
|
|
49
|
-
}
|
|
50
|
-
// Step 4: 설정 검증
|
|
51
|
-
const verifyResult2 = (0, verify_setup_1.verifySetup)(configManager);
|
|
52
|
-
if (!verifyResult2.success) {
|
|
53
|
-
installError = verifyResult2.message;
|
|
54
|
-
throw verifyResult2.error || new Error(verifyResult2.message);
|
|
62
|
+
if (results.length === 0) {
|
|
63
|
+
installError = "모든 타겟 설정 실패";
|
|
64
|
+
throw new Error(installError);
|
|
55
65
|
}
|
|
56
66
|
// Step 5: 설치 완료 알림
|
|
57
67
|
await (0, send_telemetry_1.sendTelemetry)(apiClient, true);
|
|
58
68
|
// 성공 메시지
|
|
59
69
|
logger_1.logger.success("설치 완료!");
|
|
70
|
+
console.log(chalk_1.default.green(` 설정된 도구: ${results.join(", ")}`));
|
|
60
71
|
console.log(chalk_1.default.gray("\n다음 단계:"));
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
console.log(chalk_1.default.gray(" Mac: Cmd + Q"));
|
|
64
|
-
}
|
|
65
|
-
else if (process.platform === "win32") {
|
|
66
|
-
console.log(chalk_1.default.gray(" Windows: Alt + F4"));
|
|
72
|
+
for (const name of results) {
|
|
73
|
+
console.log(chalk_1.default.white(` • ${name}를 재시작하세요`));
|
|
67
74
|
}
|
|
68
|
-
console.log(chalk_1.default.white("
|
|
69
|
-
console.log(chalk_1.default.white('3. "로그에 올려줘"라고 입력해서 연결 테스트\n'));
|
|
75
|
+
console.log(chalk_1.default.white(' • "로그에 올려줘"라고 입력해서 연결 테스트\n'));
|
|
70
76
|
process.exit(0);
|
|
71
77
|
}
|
|
72
78
|
catch (error) {
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;AAEA,kDAA0B;AAC1B,qCAAwC;AACxC,2CAA+C;AAC/C,2CAAwC;AACxC,mDAA+C;AAC/C,yDAAqD;AACrD,yDAAqD;AACrD,uDAAmD;AACnD,2DAAuD;AAEvD,MAAM,eAAe,GAAG,6BAA6B,CAAC;AAEtD,KAAK,UAAU,IAAI;IACjB,OAAO,CAAC,GAAG,CACT,eAAK,CAAC,IAAI,CAAC,IAAI,CAAC,iCAAiC,CAAC,CACnD,CAAC;IAEF,uBAAuB;IACvB,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC;IAC1C,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,eAAM,CAAC,KAAK,CACV,iCAAiC,CAClC,CAAC;QACF,eAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QACxB,eAAM,CAAC,IAAI,CACT
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create-folder.d.ts","sourceRoot":"","sources":["../../src/steps/create-folder.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAEhD,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAGtC,wBAAgB,YAAY,CAAC,aAAa,EAAE,aAAa,GAAG,UAAU,
|
|
1
|
+
{"version":3,"file":"create-folder.d.ts","sourceRoot":"","sources":["../../src/steps/create-folder.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAEhD,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAGtC,wBAAgB,YAAY,CAAC,aAAa,EAAE,aAAa,GAAG,UAAU,CAiDrE"}
|
|
@@ -37,12 +37,13 @@ exports.createFolder = createFolder;
|
|
|
37
37
|
const logger_1 = require("../utils/logger");
|
|
38
38
|
const fs = __importStar(require("fs"));
|
|
39
39
|
function createFolder(configManager) {
|
|
40
|
-
|
|
40
|
+
const { label } = configManager;
|
|
41
|
+
logger_1.logger.start(`[${label}] 설정 폴더 생성 중...`);
|
|
41
42
|
try {
|
|
42
43
|
const configDir = configManager.getConfigDir();
|
|
43
44
|
// 폴더가 이미 존재하는지 확인
|
|
44
45
|
if (fs.existsSync(configDir)) {
|
|
45
|
-
logger_1.logger.succeed(
|
|
46
|
+
logger_1.logger.succeed(`[${label}] 설정 폴더가 이미 존재합니다`);
|
|
46
47
|
return {
|
|
47
48
|
success: true,
|
|
48
49
|
message: "Config directory already exists",
|
|
@@ -50,14 +51,14 @@ function createFolder(configManager) {
|
|
|
50
51
|
}
|
|
51
52
|
// 폴더 생성
|
|
52
53
|
configManager.ensureConfigDir();
|
|
53
|
-
logger_1.logger.succeed(
|
|
54
|
+
logger_1.logger.succeed(`[${label}] 설정 폴더 생성 완료`);
|
|
54
55
|
return {
|
|
55
56
|
success: true,
|
|
56
57
|
message: "Config directory created",
|
|
57
58
|
};
|
|
58
59
|
}
|
|
59
60
|
catch (error) {
|
|
60
|
-
logger_1.logger.fail(
|
|
61
|
+
logger_1.logger.fail(`[${label}] 설정 폴더 생성 실패`);
|
|
61
62
|
// 권한 오류 처리
|
|
62
63
|
if (error instanceof Error && error.message.includes("EACCES")) {
|
|
63
64
|
logger_1.logger.error("권한 오류: 폴더를 생성할 수 없습니다", error);
|
|
@@ -71,7 +72,7 @@ function createFolder(configManager) {
|
|
|
71
72
|
}
|
|
72
73
|
return {
|
|
73
74
|
success: false,
|
|
74
|
-
message:
|
|
75
|
+
message: `Failed to create config directory for ${label}`,
|
|
75
76
|
error: error instanceof Error ? error : new Error(String(error)),
|
|
76
77
|
};
|
|
77
78
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create-folder.js","sourceRoot":"","sources":["../../src/steps/create-folder.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAKA,
|
|
1
|
+
{"version":3,"file":"create-folder.js","sourceRoot":"","sources":["../../src/steps/create-folder.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAKA,oCAiDC;AArDD,4CAAyC;AAEzC,uCAAyB;AAEzB,SAAgB,YAAY,CAAC,aAA4B;IACvD,MAAM,EAAE,KAAK,EAAE,GAAG,aAAa,CAAC;IAChC,eAAM,CAAC,KAAK,CAAC,IAAI,KAAK,iBAAiB,CAAC,CAAC;IAEzC,IAAI,CAAC;QACH,MAAM,SAAS,GAAG,aAAa,CAAC,YAAY,EAAE,CAAC;QAE/C,kBAAkB;QAClB,IAAI,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;YAC7B,eAAM,CAAC,OAAO,CAAC,IAAI,KAAK,mBAAmB,CAAC,CAAC;YAC7C,OAAO;gBACL,OAAO,EAAE,IAAI;gBACb,OAAO,EAAE,iCAAiC;aAC3C,CAAC;QACJ,CAAC;QAED,QAAQ;QACR,aAAa,CAAC,eAAe,EAAE,CAAC;QAChC,eAAM,CAAC,OAAO,CAAC,IAAI,KAAK,eAAe,CAAC,CAAC;QAEzC,OAAO;YACL,OAAO,EAAE,IAAI;YACb,OAAO,EAAE,0BAA0B;SACpC,CAAC;IACJ,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,eAAM,CAAC,IAAI,CAAC,IAAI,KAAK,eAAe,CAAC,CAAC;QAEtC,WAAW;QACX,IAAI,KAAK,YAAY,KAAK,IAAI,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC/D,eAAM,CAAC,KAAK,CACV,uBAAuB,EACvB,KAAK,CACN,CAAC;YACF,eAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YACxB,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC;gBACjC,eAAM,CAAC,IAAI,CAAC,2BAA2B,CAAC,CAAC;YAC3C,CAAC;iBAAM,CAAC;gBACN,eAAM,CAAC,IAAI,CACT,oCAAoC,aAAa,CAAC,YAAY,EAAE,EAAE,CACnE,CAAC;YACJ,CAAC;QACH,CAAC;QAED,OAAO;YACL,OAAO,EAAE,KAAK;YACd,OAAO,EAAE,yCAAyC,KAAK,EAAE;YACzD,KAAK,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;SACjE,CAAC;IACJ,CAAC;AACH,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"update-config.d.ts","sourceRoot":"","sources":["../../src/steps/update-config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAEhD,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAEtC,wBAAgB,YAAY,CAC1B,aAAa,EAAE,aAAa,EAC5B,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,GACb,UAAU,
|
|
1
|
+
{"version":3,"file":"update-config.d.ts","sourceRoot":"","sources":["../../src/steps/update-config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAEhD,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAEtC,wBAAgB,YAAY,CAC1B,aAAa,EAAE,aAAa,EAC5B,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,GACb,UAAU,CAyCZ"}
|
|
@@ -3,23 +3,24 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.updateConfig = updateConfig;
|
|
4
4
|
const logger_1 = require("../utils/logger");
|
|
5
5
|
function updateConfig(configManager, apiKey, apiUrl) {
|
|
6
|
-
|
|
6
|
+
const { label } = configManager;
|
|
7
|
+
logger_1.logger.start(`[${label}] MCP 설정 추가 중...`);
|
|
7
8
|
try {
|
|
8
9
|
// 기존 설정 파일 백업
|
|
9
10
|
if (configManager.exists()) {
|
|
10
11
|
const backupPath = configManager.backup();
|
|
11
|
-
logger_1.logger.info(
|
|
12
|
+
logger_1.logger.info(`[${label}] 기존 설정 백업 완료: ${backupPath}`);
|
|
12
13
|
}
|
|
13
14
|
// Sophia MCP 설정 추가
|
|
14
15
|
configManager.addSophiaMcp(apiKey, apiUrl);
|
|
15
|
-
logger_1.logger.succeed(
|
|
16
|
+
logger_1.logger.succeed(`[${label}] MCP 설정 추가 완료`);
|
|
16
17
|
return {
|
|
17
18
|
success: true,
|
|
18
|
-
message:
|
|
19
|
+
message: `Config updated successfully for ${label}`,
|
|
19
20
|
};
|
|
20
21
|
}
|
|
21
22
|
catch (error) {
|
|
22
|
-
logger_1.logger.fail(
|
|
23
|
+
logger_1.logger.fail(`[${label}] MCP 설정 추가 실패`);
|
|
23
24
|
// JSON 파싱 오류 처리
|
|
24
25
|
if (error instanceof Error && error.message.includes("JSON")) {
|
|
25
26
|
logger_1.logger.error("설정 파일이 손상되었습니다", error);
|
|
@@ -29,7 +30,7 @@ function updateConfig(configManager, apiKey, apiUrl) {
|
|
|
29
30
|
}
|
|
30
31
|
return {
|
|
31
32
|
success: false,
|
|
32
|
-
message:
|
|
33
|
+
message: `Failed to update config for ${label}`,
|
|
33
34
|
error: error instanceof Error ? error : new Error(String(error)),
|
|
34
35
|
};
|
|
35
36
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"update-config.js","sourceRoot":"","sources":["../../src/steps/update-config.ts"],"names":[],"mappings":";;AAIA,
|
|
1
|
+
{"version":3,"file":"update-config.js","sourceRoot":"","sources":["../../src/steps/update-config.ts"],"names":[],"mappings":";;AAIA,oCA6CC;AAhDD,4CAAyC;AAGzC,SAAgB,YAAY,CAC1B,aAA4B,EAC5B,MAAc,EACd,MAAc;IAEd,MAAM,EAAE,KAAK,EAAE,GAAG,aAAa,CAAC;IAChC,eAAM,CAAC,KAAK,CAAC,IAAI,KAAK,kBAAkB,CAAC,CAAC;IAE1C,IAAI,CAAC;QACH,cAAc;QACd,IAAI,aAAa,CAAC,MAAM,EAAE,EAAE,CAAC;YAC3B,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,EAAE,CAAC;YAC1C,eAAM,CAAC,IAAI,CAAC,IAAI,KAAK,kBAAkB,UAAU,EAAE,CAAC,CAAC;QACvD,CAAC;QAED,mBAAmB;QACnB,aAAa,CAAC,YAAY,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAC3C,eAAM,CAAC,OAAO,CAAC,IAAI,KAAK,gBAAgB,CAAC,CAAC;QAE1C,OAAO;YACL,OAAO,EAAE,IAAI;YACb,OAAO,EAAE,mCAAmC,KAAK,EAAE;SACpD,CAAC;IACJ,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,eAAM,CAAC,IAAI,CAAC,IAAI,KAAK,gBAAgB,CAAC,CAAC;QAEvC,gBAAgB;QAChB,IAAI,KAAK,YAAY,KAAK,IAAI,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;YAC7D,eAAM,CAAC,KAAK,CACV,gBAAgB,EAChB,KAAK,CACN,CAAC;YACF,eAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YACxB,eAAM,CAAC,IAAI,CACT,MAAM,aAAa,CAAC,aAAa,EAAE,YAAY,CAChD,CAAC;YACF,eAAM,CAAC,IAAI,CAAC,sBAAsB,CAAC,CAAC;QACtC,CAAC;QAED,OAAO;YACL,OAAO,EAAE,KAAK;YACd,OAAO,EAAE,+BAA+B,KAAK,EAAE;YAC/C,KAAK,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;SACjE,CAAC;IACJ,CAAC;AACH,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"verify-setup.d.ts","sourceRoot":"","sources":["../../src/steps/verify-setup.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAEhD,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAEtC,wBAAgB,WAAW,CAAC,aAAa,EAAE,aAAa,GAAG,UAAU,
|
|
1
|
+
{"version":3,"file":"verify-setup.d.ts","sourceRoot":"","sources":["../../src/steps/verify-setup.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAEhD,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAEtC,wBAAgB,WAAW,CAAC,aAAa,EAAE,aAAa,GAAG,UAAU,CAwCpE"}
|
|
@@ -3,34 +3,35 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.verifySetup = verifySetup;
|
|
4
4
|
const logger_1 = require("../utils/logger");
|
|
5
5
|
function verifySetup(configManager) {
|
|
6
|
-
|
|
6
|
+
const { label } = configManager;
|
|
7
|
+
logger_1.logger.start(`[${label}] 설정 검증 중...`);
|
|
7
8
|
try {
|
|
8
9
|
// 설정 파일 존재 확인
|
|
9
10
|
if (!configManager.exists()) {
|
|
10
|
-
throw new Error(
|
|
11
|
+
throw new Error(`Config file not found for ${label}`);
|
|
11
12
|
}
|
|
12
13
|
// 설정 파일 읽기
|
|
13
14
|
const config = configManager.read();
|
|
14
15
|
// Sophia MCP 설정 확인
|
|
15
16
|
if (!config.mcpServers?.sophia) {
|
|
16
|
-
throw new Error(
|
|
17
|
+
throw new Error(`Sophia MCP configuration not found for ${label}`);
|
|
17
18
|
}
|
|
18
19
|
const sophiaConfig = config.mcpServers.sophia;
|
|
19
20
|
// 필수 필드 확인
|
|
20
21
|
if (!sophiaConfig.command || !sophiaConfig.env?.SOPHIA_API_KEY) {
|
|
21
|
-
throw new Error(
|
|
22
|
+
throw new Error(`Sophia MCP configuration is incomplete for ${label}`);
|
|
22
23
|
}
|
|
23
|
-
logger_1.logger.succeed(
|
|
24
|
+
logger_1.logger.succeed(`[${label}] 설정 검증 완료`);
|
|
24
25
|
return {
|
|
25
26
|
success: true,
|
|
26
|
-
message:
|
|
27
|
+
message: `Setup verified successfully for ${label}`,
|
|
27
28
|
};
|
|
28
29
|
}
|
|
29
30
|
catch (error) {
|
|
30
|
-
logger_1.logger.fail(
|
|
31
|
+
logger_1.logger.fail(`[${label}] 설정 검증 실패`);
|
|
31
32
|
return {
|
|
32
33
|
success: false,
|
|
33
|
-
message:
|
|
34
|
+
message: `Setup verification failed for ${label}`,
|
|
34
35
|
error: error instanceof Error ? error : new Error(String(error)),
|
|
35
36
|
};
|
|
36
37
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"verify-setup.js","sourceRoot":"","sources":["../../src/steps/verify-setup.ts"],"names":[],"mappings":";;AAIA,
|
|
1
|
+
{"version":3,"file":"verify-setup.js","sourceRoot":"","sources":["../../src/steps/verify-setup.ts"],"names":[],"mappings":";;AAIA,kCAwCC;AA3CD,4CAAyC;AAGzC,SAAgB,WAAW,CAAC,aAA4B;IACtD,MAAM,EAAE,KAAK,EAAE,GAAG,aAAa,CAAC;IAChC,eAAM,CAAC,KAAK,CAAC,IAAI,KAAK,cAAc,CAAC,CAAC;IAEtC,IAAI,CAAC;QACH,cAAc;QACd,IAAI,CAAC,aAAa,CAAC,MAAM,EAAE,EAAE,CAAC;YAC5B,MAAM,IAAI,KAAK,CAAC,6BAA6B,KAAK,EAAE,CAAC,CAAC;QACxD,CAAC;QAED,WAAW;QACX,MAAM,MAAM,GAAG,aAAa,CAAC,IAAI,EAAE,CAAC;QAEpC,mBAAmB;QACnB,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE,MAAM,EAAE,CAAC;YAC/B,MAAM,IAAI,KAAK,CAAC,0CAA0C,KAAK,EAAE,CAAC,CAAC;QACrE,CAAC;QAED,MAAM,YAAY,GAAG,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC;QAE9C,WAAW;QACX,IAAI,CAAC,YAAY,CAAC,OAAO,IAAI,CAAC,YAAY,CAAC,GAAG,EAAE,cAAc,EAAE,CAAC;YAC/D,MAAM,IAAI,KAAK,CAAC,8CAA8C,KAAK,EAAE,CAAC,CAAC;QACzE,CAAC;QAED,eAAM,CAAC,OAAO,CAAC,IAAI,KAAK,YAAY,CAAC,CAAC;QAEtC,OAAO;YACL,OAAO,EAAE,IAAI;YACb,OAAO,EAAE,mCAAmC,KAAK,EAAE;SACpD,CAAC;IACJ,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,eAAM,CAAC,IAAI,CAAC,IAAI,KAAK,YAAY,CAAC,CAAC;QAEnC,OAAO;YACL,OAAO,EAAE,KAAK;YACd,OAAO,EAAE,iCAAiC,KAAK,EAAE;YACjD,KAAK,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;SACjE,CAAC;IACJ,CAAC;AACH,CAAC"}
|
package/dist/utils/config.d.ts
CHANGED
|
@@ -1,16 +1,23 @@
|
|
|
1
|
-
export interface
|
|
1
|
+
export interface McpConfig {
|
|
2
2
|
mcpServers?: Record<string, any>;
|
|
3
3
|
[key: string]: any;
|
|
4
4
|
}
|
|
5
|
+
export interface ConfigTarget {
|
|
6
|
+
label: string;
|
|
7
|
+
configPath: string;
|
|
8
|
+
}
|
|
5
9
|
export declare class ConfigManager {
|
|
6
10
|
private configPath;
|
|
7
|
-
|
|
11
|
+
readonly label: string;
|
|
12
|
+
constructor(label: string, configPath: string);
|
|
13
|
+
static getTargets(): ConfigTarget[];
|
|
14
|
+
static createAll(): ConfigManager[];
|
|
8
15
|
getConfigPath(): string;
|
|
9
16
|
getConfigDir(): string;
|
|
10
17
|
exists(): boolean;
|
|
11
18
|
ensureConfigDir(): void;
|
|
12
|
-
read():
|
|
13
|
-
write(config:
|
|
19
|
+
read(): McpConfig;
|
|
20
|
+
write(config: McpConfig): void;
|
|
14
21
|
backup(): string;
|
|
15
22
|
addSophiaMcp(apiKey: string, apiUrl: string): void;
|
|
16
23
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/utils/config.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/utils/config.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,SAAS;IACxB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IACjC,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;CACpB;AAED,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,qBAAa,aAAa;IACxB,OAAO,CAAC,UAAU,CAAS;IAC3B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;gBAEX,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM;IAK7C,MAAM,CAAC,UAAU,IAAI,YAAY,EAAE;IAcnC,MAAM,CAAC,SAAS,IAAI,aAAa,EAAE;IAMnC,aAAa,IAAI,MAAM;IAIvB,YAAY,IAAI,MAAM;IAItB,MAAM,IAAI,OAAO;IAIjB,eAAe,IAAI,IAAI;IAOvB,IAAI,IAAI,SAAS;IAajB,KAAK,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI;IAS9B,MAAM,IAAI,MAAM;IAUhB,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI;CAmBnD"}
|
package/dist/utils/config.js
CHANGED
|
@@ -38,10 +38,25 @@ const fs = __importStar(require("fs"));
|
|
|
38
38
|
const path = __importStar(require("path"));
|
|
39
39
|
const os = __importStar(require("os"));
|
|
40
40
|
class ConfigManager {
|
|
41
|
-
constructor() {
|
|
42
|
-
|
|
41
|
+
constructor(label, configPath) {
|
|
42
|
+
this.label = label;
|
|
43
|
+
this.configPath = configPath;
|
|
44
|
+
}
|
|
45
|
+
static getTargets() {
|
|
43
46
|
const homeDir = os.homedir();
|
|
44
|
-
|
|
47
|
+
return [
|
|
48
|
+
{
|
|
49
|
+
label: "Claude Code",
|
|
50
|
+
configPath: path.join(homeDir, ".claude", "mcp.json"),
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
label: "Cursor",
|
|
54
|
+
configPath: path.join(homeDir, ".cursor", "mcp.json"),
|
|
55
|
+
},
|
|
56
|
+
];
|
|
57
|
+
}
|
|
58
|
+
static createAll() {
|
|
59
|
+
return ConfigManager.getTargets().map((t) => new ConfigManager(t.label, t.configPath));
|
|
45
60
|
}
|
|
46
61
|
getConfigPath() {
|
|
47
62
|
return this.configPath;
|
package/dist/utils/config.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/utils/config.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,uCAAyB;AACzB,2CAA6B;AAC7B,uCAAyB;
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/utils/config.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sophia-vibelog/setup",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "One-command MCP setup for Sophia VibeLog",
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "One-command MCP setup for Sophia VibeLog (Claude Code + Cursor)",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"bin": {
|
|
7
7
|
"sophia-setup": "./dist/index.js"
|
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
"keywords": [
|
|
15
15
|
"mcp",
|
|
16
16
|
"claude",
|
|
17
|
+
"cursor",
|
|
17
18
|
"sophia",
|
|
18
19
|
"vibelog",
|
|
19
20
|
"setup"
|
package/src/index.ts
CHANGED
|
@@ -25,7 +25,7 @@ async function main() {
|
|
|
25
25
|
);
|
|
26
26
|
logger.info("\n사용 방법:");
|
|
27
27
|
logger.info(
|
|
28
|
-
"SOPHIA_API_KEY=your_key npx @sophia-
|
|
28
|
+
"SOPHIA_API_KEY=your_key npx @sophia-vibelog/setup"
|
|
29
29
|
);
|
|
30
30
|
process.exit(1);
|
|
31
31
|
}
|
|
@@ -33,41 +33,59 @@ async function main() {
|
|
|
33
33
|
const apiUrl = process.env.SOPHIA_API_URL || DEFAULT_API_URL;
|
|
34
34
|
|
|
35
35
|
const apiClient = new ApiClient(apiKey, apiUrl);
|
|
36
|
-
const
|
|
36
|
+
const managers = ConfigManager.createAll();
|
|
37
37
|
|
|
38
38
|
let installError: string | undefined;
|
|
39
39
|
|
|
40
40
|
try {
|
|
41
|
-
// Step 1: API 키 검증
|
|
41
|
+
// Step 1: API 키 검증 (한 번만)
|
|
42
42
|
const verifyResult = await verifyKey(apiClient);
|
|
43
43
|
if (!verifyResult.success) {
|
|
44
44
|
installError = verifyResult.message;
|
|
45
45
|
throw new Error(verifyResult.message);
|
|
46
46
|
}
|
|
47
47
|
|
|
48
|
-
// Step 2:
|
|
49
|
-
const
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
48
|
+
// Step 2-4: 각 타겟(Claude Code, Cursor)에 설정
|
|
49
|
+
const results: string[] = [];
|
|
50
|
+
|
|
51
|
+
for (const manager of managers) {
|
|
52
|
+
console.log(
|
|
53
|
+
chalk.cyan(`\n📦 ${manager.label} 설정 시작`)
|
|
54
|
+
);
|
|
55
|
+
|
|
56
|
+
// 폴더 생성
|
|
57
|
+
const folderResult = createFolder(manager);
|
|
58
|
+
if (!folderResult.success) {
|
|
59
|
+
logger.warn(
|
|
60
|
+
`${manager.label} 폴더 생성 실패 — 건너뜁니다`
|
|
61
|
+
);
|
|
62
|
+
continue;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// MCP 설정 추가
|
|
66
|
+
const configResult = updateConfig(manager, apiKey, apiUrl);
|
|
67
|
+
if (!configResult.success) {
|
|
68
|
+
logger.warn(
|
|
69
|
+
`${manager.label} 설정 추가 실패 — 건너뜁니다`
|
|
70
|
+
);
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// 설정 검증
|
|
75
|
+
const setupResult = verifySetup(manager);
|
|
76
|
+
if (!setupResult.success) {
|
|
77
|
+
logger.warn(
|
|
78
|
+
`${manager.label} 설정 검증 실패 — 건너뜁니다`
|
|
79
|
+
);
|
|
80
|
+
continue;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
results.push(manager.label);
|
|
53
84
|
}
|
|
54
85
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
apiKey,
|
|
59
|
-
apiUrl
|
|
60
|
-
);
|
|
61
|
-
if (!configResult.success) {
|
|
62
|
-
installError = configResult.message;
|
|
63
|
-
throw configResult.error || new Error(configResult.message);
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
// Step 4: 설정 검증
|
|
67
|
-
const verifyResult2 = verifySetup(configManager);
|
|
68
|
-
if (!verifyResult2.success) {
|
|
69
|
-
installError = verifyResult2.message;
|
|
70
|
-
throw verifyResult2.error || new Error(verifyResult2.message);
|
|
86
|
+
if (results.length === 0) {
|
|
87
|
+
installError = "모든 타겟 설정 실패";
|
|
88
|
+
throw new Error(installError);
|
|
71
89
|
}
|
|
72
90
|
|
|
73
91
|
// Step 5: 설치 완료 알림
|
|
@@ -75,16 +93,15 @@ async function main() {
|
|
|
75
93
|
|
|
76
94
|
// 성공 메시지
|
|
77
95
|
logger.success("설치 완료!");
|
|
96
|
+
console.log(
|
|
97
|
+
chalk.green(` 설정된 도구: ${results.join(", ")}`)
|
|
98
|
+
);
|
|
78
99
|
console.log(chalk.gray("\n다음 단계:"));
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
console.log(chalk.gray(" Mac: Cmd + Q"));
|
|
82
|
-
} else if (process.platform === "win32") {
|
|
83
|
-
console.log(chalk.gray(" Windows: Alt + F4"));
|
|
100
|
+
for (const name of results) {
|
|
101
|
+
console.log(chalk.white(` • ${name}를 재시작하세요`));
|
|
84
102
|
}
|
|
85
|
-
console.log(chalk.white("2. Claude Code 다시 실행"));
|
|
86
103
|
console.log(
|
|
87
|
-
chalk.white('
|
|
104
|
+
chalk.white(' • "로그에 올려줘"라고 입력해서 연결 테스트\n')
|
|
88
105
|
);
|
|
89
106
|
|
|
90
107
|
process.exit(0);
|
|
@@ -4,14 +4,15 @@ import { StepResult } from "../types";
|
|
|
4
4
|
import * as fs from "fs";
|
|
5
5
|
|
|
6
6
|
export function createFolder(configManager: ConfigManager): StepResult {
|
|
7
|
-
|
|
7
|
+
const { label } = configManager;
|
|
8
|
+
logger.start(`[${label}] 설정 폴더 생성 중...`);
|
|
8
9
|
|
|
9
10
|
try {
|
|
10
11
|
const configDir = configManager.getConfigDir();
|
|
11
12
|
|
|
12
13
|
// 폴더가 이미 존재하는지 확인
|
|
13
14
|
if (fs.existsSync(configDir)) {
|
|
14
|
-
logger.succeed(
|
|
15
|
+
logger.succeed(`[${label}] 설정 폴더가 이미 존재합니다`);
|
|
15
16
|
return {
|
|
16
17
|
success: true,
|
|
17
18
|
message: "Config directory already exists",
|
|
@@ -20,14 +21,14 @@ export function createFolder(configManager: ConfigManager): StepResult {
|
|
|
20
21
|
|
|
21
22
|
// 폴더 생성
|
|
22
23
|
configManager.ensureConfigDir();
|
|
23
|
-
logger.succeed(
|
|
24
|
+
logger.succeed(`[${label}] 설정 폴더 생성 완료`);
|
|
24
25
|
|
|
25
26
|
return {
|
|
26
27
|
success: true,
|
|
27
28
|
message: "Config directory created",
|
|
28
29
|
};
|
|
29
30
|
} catch (error) {
|
|
30
|
-
logger.fail(
|
|
31
|
+
logger.fail(`[${label}] 설정 폴더 생성 실패`);
|
|
31
32
|
|
|
32
33
|
// 권한 오류 처리
|
|
33
34
|
if (error instanceof Error && error.message.includes("EACCES")) {
|
|
@@ -47,7 +48,7 @@ export function createFolder(configManager: ConfigManager): StepResult {
|
|
|
47
48
|
|
|
48
49
|
return {
|
|
49
50
|
success: false,
|
|
50
|
-
message:
|
|
51
|
+
message: `Failed to create config directory for ${label}`,
|
|
51
52
|
error: error instanceof Error ? error : new Error(String(error)),
|
|
52
53
|
};
|
|
53
54
|
}
|
|
@@ -7,25 +7,26 @@ export function updateConfig(
|
|
|
7
7
|
apiKey: string,
|
|
8
8
|
apiUrl: string
|
|
9
9
|
): StepResult {
|
|
10
|
-
|
|
10
|
+
const { label } = configManager;
|
|
11
|
+
logger.start(`[${label}] MCP 설정 추가 중...`);
|
|
11
12
|
|
|
12
13
|
try {
|
|
13
14
|
// 기존 설정 파일 백업
|
|
14
15
|
if (configManager.exists()) {
|
|
15
16
|
const backupPath = configManager.backup();
|
|
16
|
-
logger.info(
|
|
17
|
+
logger.info(`[${label}] 기존 설정 백업 완료: ${backupPath}`);
|
|
17
18
|
}
|
|
18
19
|
|
|
19
20
|
// Sophia MCP 설정 추가
|
|
20
21
|
configManager.addSophiaMcp(apiKey, apiUrl);
|
|
21
|
-
logger.succeed(
|
|
22
|
+
logger.succeed(`[${label}] MCP 설정 추가 완료`);
|
|
22
23
|
|
|
23
24
|
return {
|
|
24
25
|
success: true,
|
|
25
|
-
message:
|
|
26
|
+
message: `Config updated successfully for ${label}`,
|
|
26
27
|
};
|
|
27
28
|
} catch (error) {
|
|
28
|
-
logger.fail(
|
|
29
|
+
logger.fail(`[${label}] MCP 설정 추가 실패`);
|
|
29
30
|
|
|
30
31
|
// JSON 파싱 오류 처리
|
|
31
32
|
if (error instanceof Error && error.message.includes("JSON")) {
|
|
@@ -42,7 +43,7 @@ export function updateConfig(
|
|
|
42
43
|
|
|
43
44
|
return {
|
|
44
45
|
success: false,
|
|
45
|
-
message:
|
|
46
|
+
message: `Failed to update config for ${label}`,
|
|
46
47
|
error: error instanceof Error ? error : new Error(String(error)),
|
|
47
48
|
};
|
|
48
49
|
}
|
|
@@ -3,12 +3,13 @@ import { logger } from "../utils/logger";
|
|
|
3
3
|
import { StepResult } from "../types";
|
|
4
4
|
|
|
5
5
|
export function verifySetup(configManager: ConfigManager): StepResult {
|
|
6
|
-
|
|
6
|
+
const { label } = configManager;
|
|
7
|
+
logger.start(`[${label}] 설정 검증 중...`);
|
|
7
8
|
|
|
8
9
|
try {
|
|
9
10
|
// 설정 파일 존재 확인
|
|
10
11
|
if (!configManager.exists()) {
|
|
11
|
-
throw new Error(
|
|
12
|
+
throw new Error(`Config file not found for ${label}`);
|
|
12
13
|
}
|
|
13
14
|
|
|
14
15
|
// 설정 파일 읽기
|
|
@@ -16,28 +17,28 @@ export function verifySetup(configManager: ConfigManager): StepResult {
|
|
|
16
17
|
|
|
17
18
|
// Sophia MCP 설정 확인
|
|
18
19
|
if (!config.mcpServers?.sophia) {
|
|
19
|
-
throw new Error(
|
|
20
|
+
throw new Error(`Sophia MCP configuration not found for ${label}`);
|
|
20
21
|
}
|
|
21
22
|
|
|
22
23
|
const sophiaConfig = config.mcpServers.sophia;
|
|
23
24
|
|
|
24
25
|
// 필수 필드 확인
|
|
25
26
|
if (!sophiaConfig.command || !sophiaConfig.env?.SOPHIA_API_KEY) {
|
|
26
|
-
throw new Error(
|
|
27
|
+
throw new Error(`Sophia MCP configuration is incomplete for ${label}`);
|
|
27
28
|
}
|
|
28
29
|
|
|
29
|
-
logger.succeed(
|
|
30
|
+
logger.succeed(`[${label}] 설정 검증 완료`);
|
|
30
31
|
|
|
31
32
|
return {
|
|
32
33
|
success: true,
|
|
33
|
-
message:
|
|
34
|
+
message: `Setup verified successfully for ${label}`,
|
|
34
35
|
};
|
|
35
36
|
} catch (error) {
|
|
36
|
-
logger.fail(
|
|
37
|
+
logger.fail(`[${label}] 설정 검증 실패`);
|
|
37
38
|
|
|
38
39
|
return {
|
|
39
40
|
success: false,
|
|
40
|
-
message:
|
|
41
|
+
message: `Setup verification failed for ${label}`,
|
|
41
42
|
error: error instanceof Error ? error : new Error(String(error)),
|
|
42
43
|
};
|
|
43
44
|
}
|
package/src/utils/config.ts
CHANGED
|
@@ -2,18 +2,43 @@ import * as fs from "fs";
|
|
|
2
2
|
import * as path from "path";
|
|
3
3
|
import * as os from "os";
|
|
4
4
|
|
|
5
|
-
export interface
|
|
5
|
+
export interface McpConfig {
|
|
6
6
|
mcpServers?: Record<string, any>;
|
|
7
7
|
[key: string]: any;
|
|
8
8
|
}
|
|
9
9
|
|
|
10
|
+
export interface ConfigTarget {
|
|
11
|
+
label: string;
|
|
12
|
+
configPath: string;
|
|
13
|
+
}
|
|
14
|
+
|
|
10
15
|
export class ConfigManager {
|
|
11
16
|
private configPath: string;
|
|
17
|
+
readonly label: string;
|
|
18
|
+
|
|
19
|
+
constructor(label: string, configPath: string) {
|
|
20
|
+
this.label = label;
|
|
21
|
+
this.configPath = configPath;
|
|
22
|
+
}
|
|
12
23
|
|
|
13
|
-
|
|
14
|
-
// Claude Code MCP 설정 파일 경로 (~/.claude/mcp.json)
|
|
24
|
+
static getTargets(): ConfigTarget[] {
|
|
15
25
|
const homeDir = os.homedir();
|
|
16
|
-
|
|
26
|
+
return [
|
|
27
|
+
{
|
|
28
|
+
label: "Claude Code",
|
|
29
|
+
configPath: path.join(homeDir, ".claude", "mcp.json"),
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
label: "Cursor",
|
|
33
|
+
configPath: path.join(homeDir, ".cursor", "mcp.json"),
|
|
34
|
+
},
|
|
35
|
+
];
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
static createAll(): ConfigManager[] {
|
|
39
|
+
return ConfigManager.getTargets().map(
|
|
40
|
+
(t) => new ConfigManager(t.label, t.configPath)
|
|
41
|
+
);
|
|
17
42
|
}
|
|
18
43
|
|
|
19
44
|
getConfigPath(): string {
|
|
@@ -35,7 +60,7 @@ export class ConfigManager {
|
|
|
35
60
|
}
|
|
36
61
|
}
|
|
37
62
|
|
|
38
|
-
read():
|
|
63
|
+
read(): McpConfig {
|
|
39
64
|
if (!this.exists()) {
|
|
40
65
|
return {};
|
|
41
66
|
}
|
|
@@ -48,7 +73,7 @@ export class ConfigManager {
|
|
|
48
73
|
}
|
|
49
74
|
}
|
|
50
75
|
|
|
51
|
-
write(config:
|
|
76
|
+
write(config: McpConfig): void {
|
|
52
77
|
try {
|
|
53
78
|
const content = JSON.stringify(config, null, 2);
|
|
54
79
|
fs.writeFileSync(this.configPath, content, "utf-8");
|