@vibecodetown/mcp-server 2.1.3 → 2.1.4
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.
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
// adapters/mcp-ts/src/local-mode/install-state.ts
|
|
2
|
+
// Installation state verification
|
|
3
|
+
import * as fs from "node:fs";
|
|
4
|
+
import { getVibeRepoPaths } from "./paths.js";
|
|
5
|
+
import { readVersionLock } from "./version-lock.js";
|
|
6
|
+
import { healthCheck } from "../bootstrap/doctor.js";
|
|
7
|
+
/**
|
|
8
|
+
* Check installation state of the repository
|
|
9
|
+
*/
|
|
10
|
+
export async function checkInstallState(repoRoot) {
|
|
11
|
+
const paths = getVibeRepoPaths(repoRoot);
|
|
12
|
+
const warnings = [];
|
|
13
|
+
// Check local init
|
|
14
|
+
const localInitialized = fs.existsSync(paths.configFile);
|
|
15
|
+
if (!localInitialized) {
|
|
16
|
+
warnings.push("로컬 모드 미초기화. 'vibe setup' 실행 필요");
|
|
17
|
+
}
|
|
18
|
+
// Check engines
|
|
19
|
+
let enginesReady = false;
|
|
20
|
+
try {
|
|
21
|
+
const health = await healthCheck();
|
|
22
|
+
enginesReady = health.engines.every(e => e.status === "ok");
|
|
23
|
+
if (!enginesReady) {
|
|
24
|
+
const missing = health.engines.filter(e => e.status !== "ok").map(e => e.name);
|
|
25
|
+
warnings.push(`엔진 누락: ${missing.join(", ")}`);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
catch {
|
|
29
|
+
warnings.push("엔진 상태 확인 실패");
|
|
30
|
+
}
|
|
31
|
+
// Check version lock
|
|
32
|
+
const versionLockExists = readVersionLock(repoRoot) !== null;
|
|
33
|
+
if (!versionLockExists && localInitialized) {
|
|
34
|
+
warnings.push("버전 잠금 파일 없음. 'vibe setup' 재실행 권장");
|
|
35
|
+
}
|
|
36
|
+
return { localInitialized, enginesReady, versionLockExists, warnings };
|
|
37
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
// adapters/mcp-ts/src/local-mode/setup.ts
|
|
2
|
+
// Unified installation logic
|
|
3
|
+
import { initLocalModeRepo } from "./init.js";
|
|
4
|
+
import { writeVersionLock } from "./version-lock.js";
|
|
5
|
+
import { ensureEngines } from "../bootstrap/installer.js";
|
|
6
|
+
import { healthCheck } from "../bootstrap/doctor.js";
|
|
7
|
+
/**
|
|
8
|
+
* Run unified setup process
|
|
9
|
+
*/
|
|
10
|
+
export async function runSetup(repoRoot, cliVersion, opts) {
|
|
11
|
+
const warnings = [];
|
|
12
|
+
// Step 1: Local mode init
|
|
13
|
+
const local = initLocalModeRepo(repoRoot, {
|
|
14
|
+
force: opts.force,
|
|
15
|
+
installHooks: opts.installHooks ?? true,
|
|
16
|
+
installCi: opts.installCi,
|
|
17
|
+
ciFailOnWarn: opts.ciFailOnWarn,
|
|
18
|
+
});
|
|
19
|
+
// Step 2: Engine installation (unless localOnly)
|
|
20
|
+
let engines = [];
|
|
21
|
+
if (!opts.localOnly) {
|
|
22
|
+
try {
|
|
23
|
+
await ensureEngines();
|
|
24
|
+
const health = await healthCheck();
|
|
25
|
+
engines = health.engines.map(e => ({
|
|
26
|
+
name: e.name,
|
|
27
|
+
version: e.version,
|
|
28
|
+
status: e.status,
|
|
29
|
+
}));
|
|
30
|
+
}
|
|
31
|
+
catch (e) {
|
|
32
|
+
warnings.push(`엔진 설치 실패: ${e instanceof Error ? e.message : String(e)}`);
|
|
33
|
+
warnings.push("오프라인 모드: vibe setup --local-only");
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
// Step 3: Version lock
|
|
37
|
+
let versionLock = null;
|
|
38
|
+
try {
|
|
39
|
+
const engineVersions = Object.fromEntries(engines.filter(e => e.status === "ok").map(e => [e.name, e.version]));
|
|
40
|
+
versionLock = writeVersionLock(repoRoot, cliVersion, engineVersions);
|
|
41
|
+
}
|
|
42
|
+
catch (e) {
|
|
43
|
+
warnings.push(`버전 잠금 파일 생성 실패: ${e instanceof Error ? e.message : String(e)}`);
|
|
44
|
+
}
|
|
45
|
+
return { local, engines, versionLock, warnings };
|
|
46
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
// adapters/mcp-ts/src/local-mode/version-lock.ts
|
|
2
|
+
// Version lock management for unified installation
|
|
3
|
+
import * as fs from "node:fs";
|
|
4
|
+
import { z } from "zod";
|
|
5
|
+
import { getVibeRepoPaths } from "./paths.js";
|
|
6
|
+
export const VersionLockSchema = z.object({
|
|
7
|
+
schema_version: z.literal(1),
|
|
8
|
+
created_at: z.string(),
|
|
9
|
+
updated_at: z.string(),
|
|
10
|
+
cli: z.object({
|
|
11
|
+
name: z.string(),
|
|
12
|
+
version: z.string(),
|
|
13
|
+
}),
|
|
14
|
+
engines: z.record(z.string(), z.object({
|
|
15
|
+
version: z.string(),
|
|
16
|
+
installed_at: z.string(),
|
|
17
|
+
})),
|
|
18
|
+
});
|
|
19
|
+
/**
|
|
20
|
+
* Read version lock file from repo
|
|
21
|
+
*/
|
|
22
|
+
export function readVersionLock(repoRoot) {
|
|
23
|
+
const paths = getVibeRepoPaths(repoRoot);
|
|
24
|
+
if (!fs.existsSync(paths.versionLockFile))
|
|
25
|
+
return null;
|
|
26
|
+
try {
|
|
27
|
+
const data = JSON.parse(fs.readFileSync(paths.versionLockFile, "utf-8"));
|
|
28
|
+
return VersionLockSchema.parse(data);
|
|
29
|
+
}
|
|
30
|
+
catch {
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Write version lock file to repo
|
|
36
|
+
*/
|
|
37
|
+
export function writeVersionLock(repoRoot, cliVersion, engines) {
|
|
38
|
+
const paths = getVibeRepoPaths(repoRoot);
|
|
39
|
+
const now = new Date().toISOString();
|
|
40
|
+
const existing = readVersionLock(repoRoot);
|
|
41
|
+
const lock = {
|
|
42
|
+
schema_version: 1,
|
|
43
|
+
created_at: existing?.created_at ?? now,
|
|
44
|
+
updated_at: now,
|
|
45
|
+
cli: { name: "@vibecode/mcp-server", version: cliVersion },
|
|
46
|
+
engines: Object.fromEntries(Object.entries(engines).map(([name, version]) => [
|
|
47
|
+
name,
|
|
48
|
+
{ version, installed_at: now }
|
|
49
|
+
])),
|
|
50
|
+
};
|
|
51
|
+
fs.writeFileSync(paths.versionLockFile, JSON.stringify(lock, null, 2) + "\n");
|
|
52
|
+
return paths.versionLockFile;
|
|
53
|
+
}
|
package/build/vibe-cli.js
CHANGED
|
@@ -14,6 +14,8 @@ import { setRepoConfigValue, validateRepoConfig } from "./local-mode/config.js";
|
|
|
14
14
|
import { getVibeRepoPaths } from "./local-mode/paths.js";
|
|
15
15
|
import { archiveCurrentWorkOrder, createWorkOrderTemplate, readCurrentWorkOrder, writeCurrentWorkOrder } from "./local-mode/work-order.js";
|
|
16
16
|
import { autoUpdateOnStart } from "./version-check.js";
|
|
17
|
+
import { runSetup } from "./local-mode/setup.js";
|
|
18
|
+
import { checkInstallState } from "./local-mode/install-state.js";
|
|
17
19
|
// ============================================================
|
|
18
20
|
// Constants
|
|
19
21
|
// ============================================================
|
|
@@ -110,7 +112,89 @@ async function cmdDoctor() {
|
|
|
110
112
|
function resolveRepoRoot() {
|
|
111
113
|
return getGitRoot(process.cwd()) ?? process.cwd();
|
|
112
114
|
}
|
|
115
|
+
async function cmdSetup() {
|
|
116
|
+
const repoRoot = resolveRepoRoot();
|
|
117
|
+
const args = process.argv.slice(2);
|
|
118
|
+
const forceFlag = args.includes("--force") || args.includes("-f");
|
|
119
|
+
const localOnly = args.includes("--local-only");
|
|
120
|
+
const checkOnly = args.includes("--check");
|
|
121
|
+
const noHooks = args.includes("--no-hooks");
|
|
122
|
+
const installCi = args.includes("--ci");
|
|
123
|
+
const ciFailOnWarn = args.includes("--strict");
|
|
124
|
+
console.log("");
|
|
125
|
+
console.log(c("cyan", "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"));
|
|
126
|
+
console.log(c("cyan", " Vibe PM Setup"));
|
|
127
|
+
console.log(c("cyan", "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"));
|
|
128
|
+
console.log("");
|
|
129
|
+
if (checkOnly) {
|
|
130
|
+
const state = await checkInstallState(repoRoot);
|
|
131
|
+
console.log(` Local: ${state.localInitialized ? c("green", "OK") : c("red", "NOT INITIALIZED")}`);
|
|
132
|
+
console.log(` Engines: ${state.enginesReady ? c("green", "OK") : c("yellow", "INCOMPLETE")}`);
|
|
133
|
+
console.log(` Version Lock: ${state.versionLockExists ? c("green", "OK") : c("yellow", "MISSING")}`);
|
|
134
|
+
if (state.warnings.length > 0) {
|
|
135
|
+
console.log("");
|
|
136
|
+
state.warnings.forEach(w => console.log(` ${c("yellow", "\u26A0")} ${w}`));
|
|
137
|
+
}
|
|
138
|
+
console.log("");
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
// Step 1: Local mode
|
|
142
|
+
console.log(" Step 1/3: 로컬 모드 초기화...");
|
|
143
|
+
// Step 2: Engines
|
|
144
|
+
if (!localOnly) {
|
|
145
|
+
console.log(" Step 2/3: 엔진 설치...");
|
|
146
|
+
}
|
|
147
|
+
else {
|
|
148
|
+
console.log(" Step 2/3: 엔진 설치 (스킵 - local-only)");
|
|
149
|
+
}
|
|
150
|
+
// Step 3: Version lock
|
|
151
|
+
console.log(" Step 3/3: 버전 잠금...");
|
|
152
|
+
const result = await runSetup(repoRoot, VERSION, {
|
|
153
|
+
force: forceFlag,
|
|
154
|
+
localOnly,
|
|
155
|
+
installHooks: !noHooks,
|
|
156
|
+
installCi,
|
|
157
|
+
ciFailOnWarn,
|
|
158
|
+
});
|
|
159
|
+
console.log("");
|
|
160
|
+
// Results
|
|
161
|
+
if (result.local.created.length > 0) {
|
|
162
|
+
console.log(` ${c("green", "\u2713")} 로컬 파일 생성: ${result.local.created.length}개`);
|
|
163
|
+
}
|
|
164
|
+
if (result.local.updated.length > 0) {
|
|
165
|
+
console.log(` ${c("yellow", "\u2191")} 로컬 파일 업데이트: ${result.local.updated.length}개`);
|
|
166
|
+
}
|
|
167
|
+
if (result.engines.length > 0) {
|
|
168
|
+
const ok = result.engines.filter(e => e.status === "ok").length;
|
|
169
|
+
console.log(` ${c("green", "\u2713")} 엔진: ${ok}/${result.engines.length} 준비됨`);
|
|
170
|
+
}
|
|
171
|
+
if (result.versionLock) {
|
|
172
|
+
console.log(` ${c("green", "\u2713")} 버전 잠금 생성됨`);
|
|
173
|
+
}
|
|
174
|
+
// Notes
|
|
175
|
+
if (result.local.notes.length > 0) {
|
|
176
|
+
console.log("");
|
|
177
|
+
console.log(" Notes:");
|
|
178
|
+
result.local.notes.forEach(n => console.log(` - ${n}`));
|
|
179
|
+
}
|
|
180
|
+
// Warnings
|
|
181
|
+
if (result.warnings.length > 0) {
|
|
182
|
+
console.log("");
|
|
183
|
+
result.warnings.forEach(w => console.log(` ${c("yellow", "\u26A0")} ${w}`));
|
|
184
|
+
}
|
|
185
|
+
console.log("");
|
|
186
|
+
console.log(c("cyan", "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"));
|
|
187
|
+
console.log(` ${c("green", "\u2713")} Setup 완료!`);
|
|
188
|
+
console.log("");
|
|
189
|
+
console.log(` Next: ${c("cyan", "vibe status")}`);
|
|
190
|
+
console.log("");
|
|
191
|
+
}
|
|
113
192
|
function cmdInit() {
|
|
193
|
+
// Deprecation warning
|
|
194
|
+
console.log("");
|
|
195
|
+
console.log(c("yellow", "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"));
|
|
196
|
+
console.log(c("yellow", " \u26A0 DEPRECATED: 'vibe init' \u2192 'vibe setup' 사용"));
|
|
197
|
+
console.log(c("yellow", "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"));
|
|
114
198
|
const repoRoot = resolveRepoRoot();
|
|
115
199
|
const args = process.argv.slice(2);
|
|
116
200
|
const forceFlag = args.includes("--force") || args.includes("-f");
|
|
@@ -429,7 +513,26 @@ async function cmdUpdate() {
|
|
|
429
513
|
}
|
|
430
514
|
// P0-1: Subcommand-specific help messages
|
|
431
515
|
const SUBCOMMAND_HELP = {
|
|
432
|
-
|
|
516
|
+
setup: `vibe setup - 통합 설치 (권장)
|
|
517
|
+
|
|
518
|
+
Usage: vibe setup [options]
|
|
519
|
+
|
|
520
|
+
Options:
|
|
521
|
+
-f, --force 기존 파일 덮어쓰기
|
|
522
|
+
--local-only 로컬 파일만 생성 (엔진 스킵)
|
|
523
|
+
--check 설치 상태 확인만
|
|
524
|
+
--no-hooks git hooks 스킵
|
|
525
|
+
--ci CI 워크플로우 설치
|
|
526
|
+
--strict CI strict 모드
|
|
527
|
+
|
|
528
|
+
Examples:
|
|
529
|
+
$ vibe setup # 전체 설치
|
|
530
|
+
$ vibe setup --check # 상태 확인
|
|
531
|
+
$ vibe setup --local-only # 오프라인
|
|
532
|
+
`,
|
|
533
|
+
init: `vibe init - [DEPRECATED] 로컬 모드 초기화
|
|
534
|
+
|
|
535
|
+
\u26A0 deprecated: 'vibe setup' 사용 권장
|
|
433
536
|
|
|
434
537
|
Usage: vibe init [options]
|
|
435
538
|
|
|
@@ -524,7 +627,8 @@ function cmdHelp(subcommand) {
|
|
|
524
627
|
console.log("Usage: vibe <command> [options]");
|
|
525
628
|
console.log("");
|
|
526
629
|
console.log("Commands:");
|
|
527
|
-
console.log(` ${c("green", "
|
|
630
|
+
console.log(` ${c("green", "setup")} 통합 설치 (권장)`);
|
|
631
|
+
console.log(` ${c("dim", "init")} [deprecated] 로컬 초기화`);
|
|
528
632
|
console.log(` ${c("green", "status")} 로컬 상태 확인`);
|
|
529
633
|
console.log(` ${c("green", "ticket")} 작업 티켓(Work Order) 생성`);
|
|
530
634
|
console.log(` ${c("green", "check")} 로컬 가드 검증 실행`);
|
|
@@ -542,12 +646,13 @@ function cmdHelp(subcommand) {
|
|
|
542
646
|
console.log(` ${c("dim", "-h, --help")} 명령어별 도움말 표시`);
|
|
543
647
|
console.log("");
|
|
544
648
|
console.log("Examples:");
|
|
545
|
-
console.log(` ${c("dim", "$")} vibe
|
|
546
|
-
console.log(` ${c("dim", "$")} vibe
|
|
649
|
+
console.log(` ${c("dim", "$")} vibe setup # 통합 설치 (권장)`);
|
|
650
|
+
console.log(` ${c("dim", "$")} vibe setup --check # 설치 상태 확인`);
|
|
651
|
+
console.log(` ${c("dim", "$")} vibe setup --help # setup 명령어 도움말`);
|
|
547
652
|
console.log(` ${c("dim", "$")} vibe ticket \"Fix auth\" # 작업 티켓 생성`);
|
|
548
653
|
console.log(` ${c("dim", "$")} vibe check # 푸시 전 로컬 검증`);
|
|
549
|
-
console.log(` ${c("dim", "$")} vibe doctor
|
|
550
|
-
console.log(` ${c("dim", "$")} vibe reset --force
|
|
654
|
+
console.log(` ${c("dim", "$")} vibe doctor # 설치 진단`);
|
|
655
|
+
console.log(` ${c("dim", "$")} vibe reset --force # 프로젝트 초기화`);
|
|
551
656
|
console.log("");
|
|
552
657
|
console.log("More info:");
|
|
553
658
|
console.log(` Documentation: ${c("blue", "https://vibecode.town/docs")}`);
|
|
@@ -576,6 +681,9 @@ async function main() {
|
|
|
576
681
|
});
|
|
577
682
|
try {
|
|
578
683
|
switch (command) {
|
|
684
|
+
case "setup":
|
|
685
|
+
await cmdSetup();
|
|
686
|
+
break;
|
|
579
687
|
case "init":
|
|
580
688
|
cmdInit();
|
|
581
689
|
break;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vibecodetown/mcp-server",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.4",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Vibe PM - AI Project Manager MCP Server for non-technical founders",
|
|
6
6
|
"keywords": [
|
|
@@ -27,9 +27,9 @@
|
|
|
27
27
|
"node": ">=18"
|
|
28
28
|
},
|
|
29
29
|
"bin": {
|
|
30
|
-
"mcp-server": "
|
|
31
|
-
"vibecode-mcp": "
|
|
32
|
-
"vibe": "
|
|
30
|
+
"mcp-server": "build/index.js",
|
|
31
|
+
"vibecode-mcp": "build/index.js",
|
|
32
|
+
"vibe": "build/vibe-cli.js"
|
|
33
33
|
},
|
|
34
34
|
"main": "./build/index.js",
|
|
35
35
|
"files": [
|