@vibeuniv/mcp-server 0.3.1 → 0.3.3
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 +5 -3
- package/dist/index.js.map +1 -1
- package/dist/lib/api-client.d.ts +16 -1
- package/dist/lib/api-client.d.ts.map +1 -1
- package/dist/lib/api-client.js +33 -0
- package/dist/lib/api-client.js.map +1 -1
- package/dist/lib/curriculum-helpers.d.ts +11 -0
- package/dist/lib/curriculum-helpers.d.ts.map +1 -0
- package/dist/lib/curriculum-helpers.js +243 -0
- package/dist/lib/curriculum-helpers.js.map +1 -0
- package/dist/lib/file-scanner.d.ts +13 -0
- package/dist/lib/file-scanner.d.ts.map +1 -1
- package/dist/lib/file-scanner.js +43 -1
- package/dist/lib/file-scanner.js.map +1 -1
- package/dist/tools/analyze.d.ts.map +1 -1
- package/dist/tools/analyze.js +13 -4
- package/dist/tools/analyze.js.map +1 -1
- package/dist/tools/ask-tutor.d.ts.map +1 -1
- package/dist/tools/ask-tutor.js +17 -5
- package/dist/tools/ask-tutor.js.map +1 -1
- package/dist/tools/generate-curriculum.d.ts.map +1 -1
- package/dist/tools/generate-curriculum.js +192 -158
- package/dist/tools/generate-curriculum.js.map +1 -1
- package/dist/tools/generate-module-content.d.ts +30 -0
- package/dist/tools/generate-module-content.d.ts.map +1 -0
- package/dist/tools/generate-module-content.js +304 -0
- package/dist/tools/generate-module-content.js.map +1 -0
- package/dist/tools/submit-analysis.d.ts.map +1 -1
- package/dist/tools/submit-analysis.js +17 -7
- package/dist/tools/submit-analysis.js.map +1 -1
- package/dist/tools/submit-curriculum.d.ts.map +1 -1
- package/dist/tools/submit-curriculum.js +66 -19
- package/dist/tools/submit-curriculum.js.map +1 -1
- package/dist/tools/submit-tech-stacks.d.ts.map +1 -1
- package/dist/tools/submit-tech-stacks.js +12 -3
- package/dist/tools/submit-tech-stacks.js.map +1 -1
- package/dist/tools/sync-project.d.ts.map +1 -1
- package/dist/tools/sync-project.js +33 -15
- package/dist/tools/sync-project.js.map +1 -1
- package/dist/types.d.ts +6 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/tools/ask-tutor.js
CHANGED
|
@@ -8,11 +8,19 @@ export function registerAskTutor(server, client) {
|
|
|
8
8
|
try {
|
|
9
9
|
console.error(`[vibeuniv] Fetching tutor context for project ${project_id}...`);
|
|
10
10
|
const context = await client.getTutorContext(project_id);
|
|
11
|
+
const locale = await client.getUserLocale();
|
|
11
12
|
// Build tutor instructions for local AI
|
|
12
13
|
let output = `## AI Tutor — Answer the student's question below\n\n`;
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
14
|
+
if (locale === "en") {
|
|
15
|
+
output += `You are a friendly tutor for a "vibe coder" — someone who built a working app with AI tools but wants to understand WHY it works.\n\n`;
|
|
16
|
+
output += `**Style:** Reference the student's actual code with file paths. Explain simply with analogies. ~500 words max. Be encouraging.\n`;
|
|
17
|
+
output += `**Rules:** Never make up code not in the project. No filler ("Great question!"). Admit unknowns honestly. **Write ALL in English.**\n\n`;
|
|
18
|
+
}
|
|
19
|
+
else {
|
|
20
|
+
output += `You are a friendly tutor for a "vibe coder" — someone who built a working app with AI tools but wants to understand WHY it works.\n\n`;
|
|
21
|
+
output += `**Style:** Reference the student's actual code with file paths. Explain simply with analogies. ~500 words max. Be encouraging.\n`;
|
|
22
|
+
output += `**Rules:** Never make up code not in the project. No filler ("Great question!"). Admit unknowns honestly. **반드시 한국어 해요체로 답변하세요.**\n\n`;
|
|
23
|
+
}
|
|
16
24
|
// Tech stacks section
|
|
17
25
|
if (context.techStacks.length > 0) {
|
|
18
26
|
output += `### Student's Project Technologies\n\n`;
|
|
@@ -40,7 +48,9 @@ export function registerAskTutor(server, client) {
|
|
|
40
48
|
// Module list with vibeuniv.com links
|
|
41
49
|
if (lc.modules && lc.modules.length > 0) {
|
|
42
50
|
output += `### Available Learning Modules\n\n`;
|
|
43
|
-
output +=
|
|
51
|
+
output += locale === "en"
|
|
52
|
+
? `Below are the student's learning modules. If a module is relevant to your answer, include a vibeuniv.com link:\n\n`
|
|
53
|
+
: `아래는 학생의 학습 모듈 목록입니다. 답변과 관련된 모듈이 있으면 vibeuniv.com 링크를 안내하세요:\n\n`;
|
|
44
54
|
for (const mod of lc.modules) {
|
|
45
55
|
output += `${mod.module_order}. [${mod.title}](https://vibeuniv.com/learning/${lc.learning_path_id}/${mod.id})\n`;
|
|
46
56
|
}
|
|
@@ -48,7 +58,9 @@ export function registerAskTutor(server, client) {
|
|
|
48
58
|
}
|
|
49
59
|
}
|
|
50
60
|
// Instruction to suggest learning links
|
|
51
|
-
output +=
|
|
61
|
+
output += locale === "en"
|
|
62
|
+
? `At the end, if a related module exists: 📚 Learn more → [Module name](link). If none, skip.\n\n`
|
|
63
|
+
: `답변 끝에 관련 모듈이 있으면: 📚 더 자세히 → [모듈명](링크) 형식으로 안내. 없으면 생략.\n\n`;
|
|
52
64
|
// User question
|
|
53
65
|
output += `### Student's Question\n\n`;
|
|
54
66
|
output += question;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ask-tutor.js","sourceRoot":"","sources":["../../src/tools/ask-tutor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAIxB,MAAM,CAAC,MAAM,cAAc,GAAG;IAC5B,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,yBAAyB,CAAC;IAC1D,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,8DAA8D,CAAC;CAC9F,CAAC;AAEF,MAAM,UAAU,gBAAgB,CAAC,MAAiB,EAAE,MAAsB;IACxE,MAAM,CAAC,IAAI,CACT,oBAAoB,EACpB,uFAAuF,EACvF,cAAc,EACd,EAAE,YAAY,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE,EAC3C,KAAK,EAAE,EAAE,UAAU,EAAE,QAAQ,EAAE,EAAE,EAAE;QACjC,IAAI,CAAC;YACH,OAAO,CAAC,KAAK,CAAC,iDAAiD,UAAU,KAAK,CAAC,CAAC;YAChF,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,eAAe,CAAC,UAAU,CAAC,CAAC;YAEzD,wCAAwC;YACxC,IAAI,MAAM,GAAG,uDAAuD,CAAC;YAErE,MAAM,IAAI,uIAAuI,CAAC;
|
|
1
|
+
{"version":3,"file":"ask-tutor.js","sourceRoot":"","sources":["../../src/tools/ask-tutor.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generate-curriculum.d.ts","sourceRoot":"","sources":["../../src/tools/generate-curriculum.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACzE,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"generate-curriculum.d.ts","sourceRoot":"","sources":["../../src/tools/generate-curriculum.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACzE,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAUtD,eAAO,MAAM,wBAAwB;;;CAMpC,CAAC;AAIF,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,cAAc,GAAG,IAAI,CA6S1F"}
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
+
import { scanTeachingCriticalFiles } from "../lib/file-scanner.js";
|
|
3
|
+
import { formatTechStack, formatKBHints, formatEducationalAnalysis, buildLevelGuidance, } from "../lib/curriculum-helpers.js";
|
|
2
4
|
export const generateCurriculumSchema = {
|
|
3
5
|
project_id: z.string().describe("The VibeUniv project ID"),
|
|
4
6
|
difficulty: z
|
|
@@ -6,141 +8,30 @@ export const generateCurriculumSchema = {
|
|
|
6
8
|
.default("beginner")
|
|
7
9
|
.describe("Target difficulty level for the curriculum"),
|
|
8
10
|
};
|
|
9
|
-
// ─── Formatting helpers ─────────────────────────────────────────────
|
|
10
|
-
function formatTechStack(t) {
|
|
11
|
-
return `- **${t.name}**${t.version ? ` v${t.version}` : ""} (${t.category})`;
|
|
12
|
-
}
|
|
13
|
-
function formatKBHints(kbHints) {
|
|
14
|
-
const sections = [];
|
|
15
|
-
for (const [techName, hints] of Object.entries(kbHints)) {
|
|
16
|
-
if (hints.length === 0)
|
|
17
|
-
continue;
|
|
18
|
-
const conceptLines = hints.map((h) => `#### ${h.concept_name} (\`${h.concept_key}\`)
|
|
19
|
-
- **핵심 포인트:**
|
|
20
|
-
${h.key_points.map((p) => ` - ${p}`).join("\n")}
|
|
21
|
-
- **좋은 퀴즈 주제:** ${h.common_quiz_topics.join(", ")}
|
|
22
|
-
- **선행 개념:** ${h.prerequisite_concepts.length > 0 ? h.prerequisite_concepts.join(", ") : "(없음)"}`).join("\n\n");
|
|
23
|
-
sections.push(`### ${techName} 핵심 개념 가이드\n\n${conceptLines}`);
|
|
24
|
-
}
|
|
25
|
-
return sections.length > 0
|
|
26
|
-
? `## 교육 핵심 포인트 (Knowledge Base)
|
|
27
|
-
|
|
28
|
-
아래는 각 기술의 **핵심 교육 포인트**입니다.
|
|
29
|
-
커리큘럼에 반드시 이 포인트들을 포함하고, 퀴즈 주제를 참고하세요.
|
|
30
|
-
선행 개념 순서에 맞게 모듈을 배치하세요.
|
|
31
|
-
|
|
32
|
-
${sections.join("\n\n")}`
|
|
33
|
-
: "";
|
|
34
|
-
}
|
|
35
|
-
function formatEducationalAnalysis(analysis, difficulty) {
|
|
36
|
-
const sections = [];
|
|
37
|
-
// Project Overview
|
|
38
|
-
const ov = analysis.project_overview;
|
|
39
|
-
sections.push(`### 프로젝트 개요 (AI 분석 결과)
|
|
40
|
-
- **앱 설명:** ${ov.one_liner}
|
|
41
|
-
- **앱 유형:** ${ov.app_type}
|
|
42
|
-
- **대상 사용자:** ${ov.target_users}
|
|
43
|
-
- **핵심 기능:** ${ov.core_features.join(", ")}`);
|
|
44
|
-
// User Flows
|
|
45
|
-
if (analysis.user_flows.length > 0) {
|
|
46
|
-
const flowLines = analysis.user_flows.map((f) => {
|
|
47
|
-
const steps = f.steps
|
|
48
|
-
.map((s) => ` - ${s.description} (\`${s.file}\`:${s.line_range})`)
|
|
49
|
-
.join("\n");
|
|
50
|
-
return `- **${f.name}** (난이도: ${f.difficulty})\n 트리거: ${f.trigger}\n${steps}`;
|
|
51
|
-
});
|
|
52
|
-
sections.push(`### 사용자 흐름 (User Flows)\n\n각 흐름을 커리큘럼에서 다뤄야 합니다:\n\n${flowLines.join("\n\n")}`);
|
|
53
|
-
}
|
|
54
|
-
// File Difficulty Map
|
|
55
|
-
if (analysis.file_analysis.length > 0) {
|
|
56
|
-
const fileLines = analysis.file_analysis
|
|
57
|
-
.sort((a, b) => a.complexity - b.complexity)
|
|
58
|
-
.map((f) => `- \`${f.path}\` — ${f.role} (복잡도: ${f.complexity}/5, ${f.difficulty})`);
|
|
59
|
-
sections.push(`### 파일 난이도 맵\n\n쉬운 파일부터 어려운 파일 순서로 정렬했습니다. 모듈 순서를 결정할 때 참고하세요:\n\n${fileLines.join("\n")}`);
|
|
60
|
-
}
|
|
61
|
-
// Learning Priorities
|
|
62
|
-
const priorities = analysis.learning_priorities;
|
|
63
|
-
const lp = difficulty === "beginner"
|
|
64
|
-
? priorities.beginner
|
|
65
|
-
: difficulty === "intermediate"
|
|
66
|
-
? priorities.intermediate
|
|
67
|
-
: priorities.advanced;
|
|
68
|
-
const priorityLines = [
|
|
69
|
-
`- **시작:** ${lp.start_with.join(", ")}`,
|
|
70
|
-
`- **집중:** ${lp.focus_on.join(", ")}`,
|
|
71
|
-
];
|
|
72
|
-
if ("skip_for_now" in lp) {
|
|
73
|
-
priorityLines.push(`- **나중에:** ${lp.skip_for_now.join(", ")}`);
|
|
74
|
-
}
|
|
75
|
-
if ("deep_dive" in lp) {
|
|
76
|
-
priorityLines.push(`- **심화:** ${lp.deep_dive.join(", ")}`);
|
|
77
|
-
}
|
|
78
|
-
if ("challenge_topics" in lp) {
|
|
79
|
-
priorityLines.push(`- **도전:** ${lp.challenge_topics.join(", ")}`);
|
|
80
|
-
}
|
|
81
|
-
sections.push(`### ${difficulty} 난이도 학습 우선순위\n\n${priorityLines.join("\n")}`);
|
|
82
|
-
// Repeated Patterns
|
|
83
|
-
if (analysis.repeated_patterns.length > 0) {
|
|
84
|
-
const patternLines = analysis.repeated_patterns.map((p) => `- **${p.name}**: ${p.description} (${p.occurrences.length}회 발견) — 교육 가치: ${p.teaching_value}`);
|
|
85
|
-
sections.push(`### 반복 패턴\n\n프로젝트에서 반복적으로 사용되는 패턴입니다. 이 패턴들을 커리큘럼에 포함하면 학습 효과가 높아집니다:\n\n${patternLines.join("\n")}`);
|
|
86
|
-
}
|
|
87
|
-
// Code Quality
|
|
88
|
-
const cq = analysis.code_quality;
|
|
89
|
-
if (cq.good_practices.length > 0 || cq.improvement_areas.length > 0) {
|
|
90
|
-
const lines = [];
|
|
91
|
-
if (cq.good_practices.length > 0) {
|
|
92
|
-
lines.push("**좋은 사례 (교육 포인트):**");
|
|
93
|
-
for (const gp of cq.good_practices) {
|
|
94
|
-
lines.push(`- ${gp.description} → 관련 개념: ${gp.concept}`);
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
if (cq.improvement_areas.length > 0) {
|
|
98
|
-
lines.push("\n**개선 기회 (학습 기회):**");
|
|
99
|
-
for (const ia of cq.improvement_areas) {
|
|
100
|
-
lines.push(`- [${ia.severity}] ${ia.description} → 교육: ${ia.teaching_opportunity}`);
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
sections.push(`### 코드 품질 관찰\n\n${lines.join("\n")}`);
|
|
104
|
-
}
|
|
105
|
-
// Tech Stack Metaphors (beginner only)
|
|
106
|
-
if (difficulty === "beginner" && ov.tech_stack_metaphors.length > 0) {
|
|
107
|
-
const metaphorLines = ov.tech_stack_metaphors.map((m) => `- **${m.tech_name}** → ${m.metaphor}`);
|
|
108
|
-
sections.push(`### 기술 스택 비유 (초보자용)\n\n이 비유들을 커리큘럼에서 적극 활용하세요:\n\n${metaphorLines.join("\n")}`);
|
|
109
|
-
}
|
|
110
|
-
return `## 프로젝트 교육 분석 (Educational Analysis)
|
|
111
|
-
|
|
112
|
-
아래는 AI가 프로젝트를 분석한 교육용 메타데이터입니다.
|
|
113
|
-
이 정보를 활용해 더 구체적이고 맞춤화된 커리큘럼을 만드세요.
|
|
114
|
-
|
|
115
|
-
${sections.join("\n\n")}`;
|
|
116
|
-
}
|
|
117
|
-
function buildLevelGuidance(difficulty) {
|
|
118
|
-
if (difficulty === "beginner") {
|
|
119
|
-
return `- "X가 뭔가요?"부터 시작 — 기술이 왜 존재하는지, 없으면 어떤 문제가 생기는지부터 설명
|
|
120
|
-
- 전문 용어를 쓸 때는 반드시 바로 뒤에 쉬운 말로 풀어서 설명 (예: "미들웨어(middleware)란, 요청이 들어올 때마다 자동으로 실행되는 '검문소' 같은 코드예요")
|
|
121
|
-
- 일상생활 비유를 적극 활용 (예: "컴포넌트는 레고 블록", "API는 식당 주문 창구", "데이터베이스는 엑셀 스프레드시트")
|
|
122
|
-
- concept과 quiz 모듈을 많이, practical은 아주 쉬운 것만
|
|
123
|
-
- 한 번에 하나의 개념만 — 여러 개념을 한꺼번에 설명하지 않기`;
|
|
124
|
-
}
|
|
125
|
-
if (difficulty === "intermediate") {
|
|
126
|
-
return `- 기본 프로그래밍 지식은 안다고 가정
|
|
127
|
-
- "어떻게"와 "왜"에 집중 — 단순 사용법이 아니라 동작 원리와 설계 이유
|
|
128
|
-
- practical과 project_walkthrough 모듈 비중 높이기
|
|
129
|
-
- 일반적인 패턴, 베스트 프랙티스, 흔한 실수 다루기`;
|
|
130
|
-
}
|
|
131
|
-
return `- 탄탄한 프로그래밍 지식 전제
|
|
132
|
-
- 고급 패턴, 성능 최적화, 아키텍처 설계에 집중
|
|
133
|
-
- practical과 project_walkthrough 비중 극대화
|
|
134
|
-
- 엣지 케이스, 내부 동작 원리, 최적화 전략 다루기`;
|
|
135
|
-
}
|
|
136
11
|
// ─── Tool registration ──────────────────────────────────────────────
|
|
137
12
|
export function registerGenerateCurriculum(server, client) {
|
|
138
|
-
server.tool("vibeuniv_generate_curriculum", "Generate a learning curriculum for the project.
|
|
13
|
+
server.tool("vibeuniv_generate_curriculum", "Pass 1 of 2: Generate a learning curriculum STRUCTURE for the project. Returns instructions to create module structure (without content sections). After generating the structure, call vibeuniv_generate_module_content for each module to generate content. IMPORTANT: Before calling, ask the user their preferred difficulty — beginner (초급), intermediate (중급), or advanced (고급).", generateCurriculumSchema, { readOnlyHint: true, openWorldHint: true }, async ({ project_id, difficulty }) => {
|
|
139
14
|
try {
|
|
140
|
-
console.error(`[vibeuniv] Generating curriculum instructions for project ${project_id}...`);
|
|
15
|
+
console.error(`[vibeuniv] Generating curriculum structure instructions for project ${project_id}...`);
|
|
141
16
|
// Fetch all curriculum context in a single API call
|
|
142
17
|
const curriculumContext = await client.getCurriculumContext(project_id);
|
|
18
|
+
// Read teaching-critical files from local disk (avoids server roundtrip for file decryption)
|
|
19
|
+
let localFiles = [];
|
|
20
|
+
try {
|
|
21
|
+
localFiles = await scanTeachingCriticalFiles(process.cwd());
|
|
22
|
+
}
|
|
23
|
+
catch (err) {
|
|
24
|
+
console.error(`[vibeuniv] Local file scan failed (non-fatal): ${err instanceof Error ? err.message : err}`);
|
|
25
|
+
}
|
|
26
|
+
// Cache context + local files for Pass 2 (generate_module_content)
|
|
27
|
+
client.setCachedCurriculumData(project_id, curriculumContext, localFiles);
|
|
28
|
+
// Prefer local files; fall back to server files if local scan yields nothing
|
|
29
|
+
const curriculumFiles = localFiles.length > 0
|
|
30
|
+
? localFiles
|
|
31
|
+
: (curriculumContext.files ?? []);
|
|
143
32
|
const techStacks = curriculumContext.techStacks;
|
|
33
|
+
const locale = curriculumContext.locale ?? "ko";
|
|
34
|
+
const en = locale === "en";
|
|
144
35
|
if (techStacks.length === 0) {
|
|
145
36
|
return {
|
|
146
37
|
content: [
|
|
@@ -162,18 +53,18 @@ export function registerGenerateCurriculum(server, client) {
|
|
|
162
53
|
const coreList = coreStacks.map(formatTechStack).join("\n");
|
|
163
54
|
const supportingList = supportingStacks.length > 0
|
|
164
55
|
? supportingStacks.map(formatTechStack).join("\n")
|
|
165
|
-
: "(없음)";
|
|
166
|
-
const levelGuidance = buildLevelGuidance(difficulty);
|
|
56
|
+
: en ? "(none)" : "(없음)";
|
|
57
|
+
const levelGuidance = buildLevelGuidance(difficulty, locale);
|
|
167
58
|
// Build KB hints section
|
|
168
59
|
const kbSection = kbResult && Object.keys(kbResult.techs).length > 0
|
|
169
|
-
? `\n${formatKBHints(kbResult.techs)}\n`
|
|
60
|
+
? `\n${formatKBHints(kbResult.techs, locale)}\n`
|
|
170
61
|
: "";
|
|
171
62
|
// Build educational analysis section (with defensive try/catch for LLM-generated data)
|
|
172
63
|
let eduSection = "";
|
|
173
64
|
let hasEduAnalysis = false;
|
|
174
65
|
if (educationalAnalysis) {
|
|
175
66
|
try {
|
|
176
|
-
eduSection = `\n${formatEducationalAnalysis(educationalAnalysis, difficulty)}\n`;
|
|
67
|
+
eduSection = `\n${formatEducationalAnalysis(educationalAnalysis, difficulty, locale)}\n`;
|
|
177
68
|
hasEduAnalysis = true;
|
|
178
69
|
}
|
|
179
70
|
catch (err) {
|
|
@@ -182,13 +73,118 @@ export function registerGenerateCurriculum(server, client) {
|
|
|
182
73
|
}
|
|
183
74
|
// Build educational analysis instruction
|
|
184
75
|
const eduInstruction = hasEduAnalysis
|
|
185
|
-
?
|
|
76
|
+
? en
|
|
77
|
+
? `\n**Educational Analysis Usage:** Project overview→intro, User Flows→walkthrough, File difficulty→module order, Learning priorities→arrangement, Repeated patterns→quizzes, Code quality→teaching points${difficulty === "beginner" ? ", Metaphors→explanations" : ""}`
|
|
78
|
+
: `\n**교육 분석 활용:** 프로젝트 개요→소개, User Flows→walkthrough, 파일 난이도→모듈 순서, 학습 우선순위→배치, 반복 패턴→퀴즈, 코드 품질→교육 포인트${difficulty === "beginner" ? ", 비유→explanation" : ""}`
|
|
186
79
|
: "";
|
|
187
80
|
// Build KB instruction
|
|
188
81
|
const kbInstruction = kbResult && Object.keys(kbResult.techs).length > 0
|
|
189
|
-
?
|
|
82
|
+
? en
|
|
83
|
+
? `\n**KB Usage:** Include key points, use quiz topics, follow prerequisite ordering.`
|
|
84
|
+
: `\n**KB 활용:** 핵심 포인트 필수 포함, 퀴즈 주제 활용, 선행 개념 순서 준수.`
|
|
85
|
+
: "";
|
|
86
|
+
// Build project source code section (local files preferred, server fallback)
|
|
87
|
+
const filesSection = curriculumFiles.length > 0
|
|
88
|
+
? en
|
|
89
|
+
? `\n## Project Source Code
|
|
90
|
+
|
|
91
|
+
Below are the student's actual project files.
|
|
92
|
+
Use these to design modules around actual project features and files.
|
|
93
|
+
|
|
94
|
+
${curriculumFiles.map((f) => `#### ${f.file_path}\n\`\`\`\n${f.content}\n\`\`\``).join("\n\n")}\n`
|
|
95
|
+
: `\n## 프로젝트 소스 코드
|
|
96
|
+
|
|
97
|
+
아래는 학생의 실제 프로젝트 파일입니다.
|
|
98
|
+
실제 프로젝트 기능/파일을 중심으로 모듈을 설계하세요.
|
|
99
|
+
|
|
100
|
+
${curriculumFiles.map((f) => `#### ${f.file_path}\n\`\`\`\n${f.content}\n\`\`\``).join("\n\n")}\n`
|
|
190
101
|
: "";
|
|
191
|
-
const instructions =
|
|
102
|
+
const instructions = en
|
|
103
|
+
? `Please generate a learning curriculum STRUCTURE for this project.
|
|
104
|
+
|
|
105
|
+
## Target: Vibe Coder (${difficulty})
|
|
106
|
+
|
|
107
|
+
Someone who built an app using AI coding tools but wants to understand **why it works**. Project-based learning, no abstract theory.
|
|
108
|
+
|
|
109
|
+
## Tech Stack
|
|
110
|
+
|
|
111
|
+
**Core (Required):**
|
|
112
|
+
${coreList}
|
|
113
|
+
|
|
114
|
+
**Supporting (Optional):**
|
|
115
|
+
${supportingList}
|
|
116
|
+
${filesSection}${eduSection}${kbSection}
|
|
117
|
+
## Design Principles
|
|
118
|
+
|
|
119
|
+
**Module Count (Required — server will reject if below minimum):**
|
|
120
|
+
- Minimum 10 modules total (aim for 10-15)
|
|
121
|
+
- Core technologies: at least 2 modules each
|
|
122
|
+
- Supporting technologies: at least 1 module each
|
|
123
|
+
|
|
124
|
+
**Module Design — Focus on project features:**
|
|
125
|
+
Design modules around the project's actual features/files, not generic tech modules ("React Basics").
|
|
126
|
+
|
|
127
|
+
Good examples:
|
|
128
|
+
- "Dashboard Layout Analysis — Authentication with Server Components" (app/(dashboard)/layout.tsx)
|
|
129
|
+
- "API Routes and Middleware — Auth Checks and Rate Limiting" (middleware.ts, app/api/...)
|
|
130
|
+
- "Supabase Connection — Server vs Browser Client Differences" (lib/supabase/server.ts, client.ts)
|
|
131
|
+
|
|
132
|
+
Bad examples:
|
|
133
|
+
- "React Basics" (too generic)
|
|
134
|
+
- "TypeScript Introduction" (unrelated to project)
|
|
135
|
+
|
|
136
|
+
**Module Order:** Start from project entry points (page.tsx, layout.tsx) → core features → advanced patterns
|
|
137
|
+
**Each module must center around at least one project file**
|
|
138
|
+
|
|
139
|
+
**Module Types:** concept (concept+analogy), practical (code practice), quiz (code-based quiz), project_walkthrough (line-by-line file reading)
|
|
140
|
+
**Difficulty:**
|
|
141
|
+
${levelGuidance}
|
|
142
|
+
${eduInstruction}${kbInstruction}
|
|
143
|
+
|
|
144
|
+
## JSON Schema (Structure Only)
|
|
145
|
+
|
|
146
|
+
Output ONLY JSON (no code fences/explanations). Do NOT include "content" or "sections" — those will be generated per-module in the next step.
|
|
147
|
+
|
|
148
|
+
{
|
|
149
|
+
"title": "string (required) — Curriculum title",
|
|
150
|
+
"description": "string (required) — Curriculum description",
|
|
151
|
+
"difficulty": "${difficulty}",
|
|
152
|
+
"estimated_hours": number (optional),
|
|
153
|
+
"modules": [
|
|
154
|
+
{
|
|
155
|
+
"title": "string (required) — Module title",
|
|
156
|
+
"description": "string (required) — Module description",
|
|
157
|
+
"module_type": "concept | practical | quiz | project_walkthrough",
|
|
158
|
+
"estimated_minutes": number (15-45),
|
|
159
|
+
"tech_name": "string (required) — Must exactly match a name from the tech stack list above"
|
|
160
|
+
}
|
|
161
|
+
]
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
**Required:**
|
|
165
|
+
- Minimum 10 modules (aim for 10-15)
|
|
166
|
+
- Core technologies: at least 2 modules each
|
|
167
|
+
- Supporting technologies: at least 1 module each
|
|
168
|
+
- Do NOT include "content" or "sections"
|
|
169
|
+
|
|
170
|
+
## Next Steps (2-Pass Orchestration)
|
|
171
|
+
|
|
172
|
+
After generating the structure JSON above:
|
|
173
|
+
1. For each module (index 0 to N-1), call:
|
|
174
|
+
vibeuniv_generate_module_content({
|
|
175
|
+
project_id: "${project_id}",
|
|
176
|
+
module_index: <0-based index>,
|
|
177
|
+
module: <module object from the structure>,
|
|
178
|
+
difficulty: "${difficulty}",
|
|
179
|
+
total_modules: <total module count>
|
|
180
|
+
})
|
|
181
|
+
2. Each call returns instructions to generate that module's content sections
|
|
182
|
+
3. Generate the sections JSON array for each module
|
|
183
|
+
4. After ALL modules have content, assemble the final curriculum:
|
|
184
|
+
- Take the structure JSON from step above
|
|
185
|
+
- Add "content": { "sections": <generated sections array> } to each module
|
|
186
|
+
5. Submit: vibeuniv_submit_curriculum({ project_id: "${project_id}", curriculum: <complete JSON> })`
|
|
187
|
+
: `이 프로젝트의 학습 커리큘럼 구조를 생성해주세요.
|
|
192
188
|
|
|
193
189
|
## 대상: 바이브 코더 (${difficulty})
|
|
194
190
|
|
|
@@ -201,39 +197,77 @@ ${coreList}
|
|
|
201
197
|
|
|
202
198
|
**Supporting (선택):**
|
|
203
199
|
${supportingList}
|
|
204
|
-
${eduSection}${kbSection}
|
|
200
|
+
${filesSection}${eduSection}${kbSection}
|
|
205
201
|
## 설계 원칙
|
|
206
202
|
|
|
207
|
-
**모듈
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
203
|
+
**모듈 수량 (필수 — 미달 시 서버에서 거부됨):**
|
|
204
|
+
- 전체 최소 10개 모듈 (10-15개 권장)
|
|
205
|
+
- Core 기술: 각 최소 2개 모듈
|
|
206
|
+
- Supporting 기술: 각 최소 1개 모듈
|
|
211
207
|
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
- code_example: 학생 실제 코드 복사 + 한국어 주석
|
|
215
|
-
- quiz_question: 4지선다(0-indexed), quiz_explanation에 정답/오답 이유
|
|
216
|
-
- challenge: 수정 파일+내용+결과 명시, starter_code(TODO 뼈대)+answer_code
|
|
217
|
-
- reflection: 1-3문장 "생각해보기"
|
|
208
|
+
**모듈 구성 — 프로젝트 기능 중심으로 설계:**
|
|
209
|
+
기술별 일반 모듈("React 기초")이 아닌, 프로젝트의 실제 기능/파일을 중심으로 설계하세요.
|
|
218
210
|
|
|
219
|
-
|
|
211
|
+
좋은 예:
|
|
212
|
+
- "대시보드 레이아웃 분석 — Server Component로 인증 처리하기" (app/(dashboard)/layout.tsx)
|
|
213
|
+
- "API 라우트와 미들웨어 — 인증 체크와 속도 제한" (middleware.ts, app/api/...)
|
|
214
|
+
- "Supabase 연결 — 서버 vs 브라우저 클라이언트 차이" (lib/supabase/server.ts, client.ts)
|
|
220
215
|
|
|
221
|
-
|
|
216
|
+
나쁜 예:
|
|
217
|
+
- "React 기초" (너무 일반적)
|
|
218
|
+
- "TypeScript 입문" (프로젝트와 무관)
|
|
222
219
|
|
|
223
|
-
|
|
220
|
+
**모듈 순서:** 프로젝트의 진입점(page.tsx, layout.tsx)부터 → 핵심 기능 → 고급 패턴
|
|
221
|
+
**각 모듈은 반드시 1개 이상의 프로젝트 파일을 중심으로 설명**
|
|
222
|
+
|
|
223
|
+
**모듈 유형:** concept(개념+비유), practical(코드 실습), quiz(코드 기반 퀴즈), project_walkthrough(파일 라인별 읽기)
|
|
224
|
+
**난이도:**
|
|
225
|
+
${levelGuidance}
|
|
224
226
|
${eduInstruction}${kbInstruction}
|
|
225
227
|
|
|
226
|
-
## JSON 스키마
|
|
228
|
+
## JSON 스키마 (구조만)
|
|
229
|
+
|
|
230
|
+
아래 구조를 정확히 따르세요. JSON만 출력 (코드 펜스/설명 없이). "content"나 "sections"는 포함하지 마세요 — 다음 단계에서 모듈별로 생성됩니다.
|
|
231
|
+
|
|
232
|
+
{
|
|
233
|
+
"title": "string (필수) — 커리큘럼 제목",
|
|
234
|
+
"description": "string (필수) — 커리큘럼 설명",
|
|
235
|
+
"difficulty": "${difficulty}",
|
|
236
|
+
"estimated_hours": number (선택),
|
|
237
|
+
"modules": [
|
|
238
|
+
{
|
|
239
|
+
"title": "string (필수) — 모듈 제목",
|
|
240
|
+
"description": "string (필수) — 모듈 설명",
|
|
241
|
+
"module_type": "concept | practical | quiz | project_walkthrough",
|
|
242
|
+
"estimated_minutes": number (15-45),
|
|
243
|
+
"tech_name": "string (필수) — 위 기술 스택 목록의 이름과 정확히 일치"
|
|
244
|
+
}
|
|
245
|
+
]
|
|
246
|
+
}
|
|
227
247
|
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
248
|
+
**필수:**
|
|
249
|
+
- 최소 10개 모듈 (10-15개 권장)
|
|
250
|
+
- Core 기술: 각 최소 2개 모듈
|
|
251
|
+
- Supporting 기술: 각 최소 1개 모듈
|
|
252
|
+
- "content"나 "sections" 포함 금지
|
|
233
253
|
|
|
234
|
-
|
|
254
|
+
## 다음 단계 (2-Pass 오케스트레이션)
|
|
235
255
|
|
|
236
|
-
|
|
256
|
+
위 구조 JSON을 생성한 후:
|
|
257
|
+
1. 각 모듈(인덱스 0부터 N-1)에 대해 호출:
|
|
258
|
+
vibeuniv_generate_module_content({
|
|
259
|
+
project_id: "${project_id}",
|
|
260
|
+
module_index: <0부터 시작하는 인덱스>,
|
|
261
|
+
module: <구조에서 해당 모듈 객체>,
|
|
262
|
+
difficulty: "${difficulty}",
|
|
263
|
+
total_modules: <전체 모듈 수>
|
|
264
|
+
})
|
|
265
|
+
2. 각 호출은 해당 모듈의 콘텐츠 섹션 생성 지시문을 반환합니다
|
|
266
|
+
3. 각 모듈의 섹션 JSON 배열을 생성하세요
|
|
267
|
+
4. 모든 모듈의 콘텐츠가 완성되면 최종 커리큘럼을 조합:
|
|
268
|
+
- 위에서 생성한 구조 JSON을 가져와
|
|
269
|
+
- 각 모듈에 "content": { "sections": <생성된 섹션 배열> } 추가
|
|
270
|
+
5. 제출: vibeuniv_submit_curriculum({ project_id: "${project_id}", curriculum: <완성 JSON> })`;
|
|
237
271
|
return {
|
|
238
272
|
content: [
|
|
239
273
|
{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generate-curriculum.js","sourceRoot":"","sources":["../../src/tools/generate-curriculum.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"generate-curriculum.js","sourceRoot":"","sources":["../../src/tools/generate-curriculum.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
3
|
+
import { VibeUnivClient } from "../lib/api-client.js";
|
|
4
|
+
export declare const generateModuleContentSchema: {
|
|
5
|
+
project_id: z.ZodString;
|
|
6
|
+
module_index: z.ZodNumber;
|
|
7
|
+
module: z.ZodObject<{
|
|
8
|
+
title: z.ZodString;
|
|
9
|
+
description: z.ZodString;
|
|
10
|
+
module_type: z.ZodString;
|
|
11
|
+
tech_name: z.ZodString;
|
|
12
|
+
estimated_minutes: z.ZodOptional<z.ZodNumber>;
|
|
13
|
+
}, "strip", z.ZodTypeAny, {
|
|
14
|
+
title: string;
|
|
15
|
+
description: string;
|
|
16
|
+
module_type: string;
|
|
17
|
+
tech_name: string;
|
|
18
|
+
estimated_minutes?: number | undefined;
|
|
19
|
+
}, {
|
|
20
|
+
title: string;
|
|
21
|
+
description: string;
|
|
22
|
+
module_type: string;
|
|
23
|
+
tech_name: string;
|
|
24
|
+
estimated_minutes?: number | undefined;
|
|
25
|
+
}>;
|
|
26
|
+
difficulty: z.ZodDefault<z.ZodEnum<["beginner", "intermediate", "advanced"]>>;
|
|
27
|
+
total_modules: z.ZodNumber;
|
|
28
|
+
};
|
|
29
|
+
export declare function registerGenerateModuleContent(server: McpServer, client: VibeUnivClient): void;
|
|
30
|
+
//# sourceMappingURL=generate-module-content.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generate-module-content.d.ts","sourceRoot":"","sources":["../../src/tools/generate-module-content.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACzE,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAWtD,eAAO,MAAM,2BAA2B;;;;;;;;;;;;;;;;;;;;;;;;CAiBvC,CAAC;AAEF,wBAAgB,6BAA6B,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,cAAc,GAAG,IAAI,CAyS7F"}
|