@syke1/mcp-server 1.4.15 → 1.4.16
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/ai/analyzer.js +4 -46
- package/dist/ai/realtime-analyzer.js +13 -68
- package/dist/config.d.ts +0 -5
- package/dist/config.js +0 -17
- package/dist/index.js +4 -4
- package/package.json +1 -1
package/dist/ai/analyzer.js
CHANGED
|
@@ -38,7 +38,6 @@ const fs = __importStar(require("fs"));
|
|
|
38
38
|
const path = __importStar(require("path"));
|
|
39
39
|
const provider_1 = require("./provider");
|
|
40
40
|
const context_extractor_1 = require("./context-extractor");
|
|
41
|
-
const config_1 = require("../config");
|
|
42
41
|
function readFileContent(filePath) {
|
|
43
42
|
try {
|
|
44
43
|
return fs.readFileSync(filePath, "utf-8");
|
|
@@ -49,27 +48,6 @@ function readFileContent(filePath) {
|
|
|
49
48
|
}
|
|
50
49
|
function buildSystemPrompt(languages) {
|
|
51
50
|
const langNames = languages.length > 0 ? languages.join("/") : "source";
|
|
52
|
-
const ko = (0, config_1.getLanguage)() === "ko";
|
|
53
|
-
if (ko) {
|
|
54
|
-
return `당신은 ${langNames} 코드 영향도 분석 전문가입니다.
|
|
55
|
-
주어진 파일의 소스코드와 이 파일에 의존하는 파일들의 코드를 분석하여,
|
|
56
|
-
이 파일을 수정할 때 어떤 부분이 깨질 수 있는지 구체적으로 설명해주세요.
|
|
57
|
-
|
|
58
|
-
분석 포맷:
|
|
59
|
-
## 핵심 역할
|
|
60
|
-
이 파일이 프로젝트에서 하는 역할을 한 문장으로 설명
|
|
61
|
-
|
|
62
|
-
## 수정 시 위험 포인트
|
|
63
|
-
수정 시 깨질 수 있는 구체적인 부분들 (함수명, 클래스명 포함)
|
|
64
|
-
|
|
65
|
-
## 영향받는 파일 분석
|
|
66
|
-
의존 파일들이 이 파일의 어떤 부분을 사용하는지 구체적으로
|
|
67
|
-
|
|
68
|
-
## 안전한 수정 가이드
|
|
69
|
-
이 파일을 수정할 때 주의할 점과 추천 접근법
|
|
70
|
-
|
|
71
|
-
한국어로 답변하세요. 간결하되 구체적으로 작성하세요.`;
|
|
72
|
-
}
|
|
73
51
|
return `You are an expert in ${langNames} code impact analysis.
|
|
74
52
|
Analyze the source code of the given file and its dependents to identify
|
|
75
53
|
what could break when this file is modified.
|
|
@@ -91,17 +69,12 @@ Be concise but specific.`;
|
|
|
91
69
|
}
|
|
92
70
|
async function analyzeWithAI(filePath, impactResult, graph) {
|
|
93
71
|
const provider = (0, provider_1.getAIProvider)();
|
|
94
|
-
const ko = (0, config_1.getLanguage)() === "ko";
|
|
95
72
|
if (!provider) {
|
|
96
|
-
return
|
|
97
|
-
? "AI 분석 비활성화 — GEMINI_KEY, OPENAI_KEY, 또는 ANTHROPIC_KEY를 설정하세요."
|
|
98
|
-
: "AI analysis disabled — set GEMINI_KEY, OPENAI_KEY, or ANTHROPIC_KEY.";
|
|
73
|
+
return "AI analysis disabled — set GEMINI_KEY, OPENAI_KEY, or ANTHROPIC_KEY.";
|
|
99
74
|
}
|
|
100
75
|
const targetSource = readFileContent(filePath);
|
|
101
76
|
if (!targetSource) {
|
|
102
|
-
return
|
|
103
|
-
? `파일을 읽을 수 없습니다: ${filePath}`
|
|
104
|
-
: `Cannot read file: ${filePath}`;
|
|
77
|
+
return `Cannot read file: ${filePath}`;
|
|
105
78
|
}
|
|
106
79
|
const codeBlockLang = graph.languages[0] || "text";
|
|
107
80
|
// Build smart context for the target file
|
|
@@ -117,20 +90,7 @@ async function analyzeWithAI(filePath, impactResult, graph) {
|
|
|
117
90
|
dependentSources.push(`### ${rel}\n\`\`\`${codeBlockLang}\n${smartDep}\n\`\`\``);
|
|
118
91
|
}
|
|
119
92
|
}
|
|
120
|
-
const userPrompt =
|
|
121
|
-
? `## 분석 대상 파일: ${impactResult.relativePath}
|
|
122
|
-
- 위험도: ${impactResult.riskLevel}
|
|
123
|
-
- 직접 의존 파일 수: ${impactResult.directDependents.length}
|
|
124
|
-
- 전이적 의존 파일 수: ${impactResult.transitiveDependents.length}
|
|
125
|
-
- 총 영향 파일 수: ${impactResult.totalImpacted}
|
|
126
|
-
|
|
127
|
-
### 대상 파일 소스코드
|
|
128
|
-
\`\`\`${codeBlockLang}
|
|
129
|
-
${smartTarget}
|
|
130
|
-
\`\`\`
|
|
131
|
-
|
|
132
|
-
${dependentSources.length > 0 ? `### 이 파일에 의존하는 파일들 (상위 ${dependentSources.length}개)\n${dependentSources.join("\n\n")}` : "이 파일에 의존하는 내부 파일이 없습니다."}`
|
|
133
|
-
: `## Target file: ${impactResult.relativePath}
|
|
93
|
+
const userPrompt = `## Target file: ${impactResult.relativePath}
|
|
134
94
|
- Risk level: ${impactResult.riskLevel}
|
|
135
95
|
- Direct dependents: ${impactResult.directDependents.length}
|
|
136
96
|
- Transitive dependents: ${impactResult.transitiveDependents.length}
|
|
@@ -147,8 +107,6 @@ ${dependentSources.length > 0 ? `### Files depending on this file (top ${depende
|
|
|
147
107
|
return await provider.analyze(systemPrompt, userPrompt);
|
|
148
108
|
}
|
|
149
109
|
catch (err) {
|
|
150
|
-
return
|
|
151
|
-
? `AI 분석 중 오류 발생: ${err.message || err}`
|
|
152
|
-
: `AI analysis error: ${err.message || err}`;
|
|
110
|
+
return `AI analysis error: ${err.message || err}`;
|
|
153
111
|
}
|
|
154
112
|
}
|
|
@@ -38,38 +38,7 @@ const analyze_impact_1 = require("../tools/analyze-impact");
|
|
|
38
38
|
const path = __importStar(require("path"));
|
|
39
39
|
const provider_1 = require("./provider");
|
|
40
40
|
const context_extractor_1 = require("./context-extractor");
|
|
41
|
-
const config_1 = require("../config");
|
|
42
41
|
function getSystemPrompt() {
|
|
43
|
-
const ko = (0, config_1.getLanguage)() === "ko";
|
|
44
|
-
if (ko) {
|
|
45
|
-
return `당신은 20년 경력의 풀스택 아키텍트이자, 코드 영향도 감시 AI입니다.
|
|
46
|
-
역할: 파일이 수정/추가/삭제될 때, 빌드 전에 잠재적 오류와 연쇄 영향을 감지합니다.
|
|
47
|
-
|
|
48
|
-
분석 원칙:
|
|
49
|
-
1. import/export 깨짐: 삭제/이름변경된 클래스/함수/변수가 다른 파일에서 참조되는지 확인
|
|
50
|
-
2. 타입 불일치: 매개변수 타입, 반환 타입 변경이 호출부와 맞는지 확인
|
|
51
|
-
3. 상태 관리 연쇄: Provider/Notifier 변경이 UI와 비즈니스 로직에 미치는 영향
|
|
52
|
-
4. 라우팅 영향: GoRouter 경로/매개변수 변경이 네비게이션에 미치는 영향
|
|
53
|
-
5. 누락된 초기화: 새로 추가된 Provider가 적절히 등록되었는지
|
|
54
|
-
|
|
55
|
-
응답 형식 (반드시 JSON):
|
|
56
|
-
{
|
|
57
|
-
"riskLevel": "CRITICAL|HIGH|MEDIUM|LOW|SAFE",
|
|
58
|
-
"summary": "한 줄 요약",
|
|
59
|
-
"brokenImports": ["깨질 수 있는 import 목록"],
|
|
60
|
-
"sideEffects": ["예상되는 부작용 목록"],
|
|
61
|
-
"warnings": ["주의사항 목록"],
|
|
62
|
-
"suggestion": "추천 조치"
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
CRITICAL: 빌드 실패 확실
|
|
66
|
-
HIGH: 런타임 오류 가능
|
|
67
|
-
MEDIUM: 기능 동작 변경 가능
|
|
68
|
-
LOW: 사소한 영향
|
|
69
|
-
SAFE: 안전한 변경
|
|
70
|
-
|
|
71
|
-
JSON만 응답하세요. 설명 텍스트 없이 순수 JSON만.`;
|
|
72
|
-
}
|
|
73
42
|
return `You are a senior full-stack architect and code impact monitoring AI with 20 years of experience.
|
|
74
43
|
Role: Detect potential errors and cascading impacts before build when files are modified/added/deleted.
|
|
75
44
|
|
|
@@ -106,7 +75,6 @@ async function analyzeChangeRealtime(change, graph, getFileContent) {
|
|
|
106
75
|
const start = Date.now();
|
|
107
76
|
const relPath = change.relativePath;
|
|
108
77
|
const codeBlockLang = graph.languages[0] || "text";
|
|
109
|
-
const ko = (0, config_1.getLanguage)() === "ko";
|
|
110
78
|
// Get impacted files from graph
|
|
111
79
|
const absPath = path.normalize(path.join(graph.sourceDir, relPath));
|
|
112
80
|
let affectedNodes = [];
|
|
@@ -130,13 +98,11 @@ async function analyzeChangeRealtime(change, graph, getFileContent) {
|
|
|
130
98
|
// Build diff summary with signature changes
|
|
131
99
|
let diffSummary = "";
|
|
132
100
|
if (change.type === "deleted") {
|
|
133
|
-
|
|
134
|
-
diffSummary = `${label}\n\`\`\`${codeBlockLang}\n${(change.oldContent || "").split("\n").slice(0, 40).join("\n")}\n\`\`\``;
|
|
101
|
+
diffSummary = `File deleted. Previous content:\n\`\`\`${codeBlockLang}\n${(change.oldContent || "").split("\n").slice(0, 40).join("\n")}\n\`\`\``;
|
|
135
102
|
}
|
|
136
103
|
else if (change.type === "added") {
|
|
137
104
|
const smartNew = (0, context_extractor_1.buildSmartContext)(change.newContent || "", codeBlockLang);
|
|
138
|
-
|
|
139
|
-
diffSummary = `${label}\n\`\`\`${codeBlockLang}\n${smartNew}\n\`\`\``;
|
|
105
|
+
diffSummary = `New file added:\n\`\`\`${codeBlockLang}\n${smartNew}\n\`\`\``;
|
|
140
106
|
}
|
|
141
107
|
else {
|
|
142
108
|
// Modified — include signature diff
|
|
@@ -147,50 +113,31 @@ async function analyzeChangeRealtime(change, graph, getFileContent) {
|
|
|
147
113
|
return `- L${d.line}: ${d.old}`;
|
|
148
114
|
return `~ L${d.line}: ${d.old} → ${d.new}`;
|
|
149
115
|
});
|
|
150
|
-
|
|
151
|
-
? `변경된 라인 (${change.diff.length}개 중 상위 30개):`
|
|
152
|
-
: `Changed lines (top 30 of ${change.diff.length}):`;
|
|
153
|
-
diffSummary = `${label}\n\`\`\`\n${diffLines.join("\n")}\n\`\`\``;
|
|
116
|
+
diffSummary = `Changed lines (top 30 of ${change.diff.length}):\n\`\`\`\n${diffLines.join("\n")}\n\`\`\``;
|
|
154
117
|
// Add structural signature changes
|
|
155
118
|
if (change.oldContent && change.newContent) {
|
|
156
119
|
const sigChanges = (0, context_extractor_1.diffSignatures)(change.oldContent, change.newContent, codeBlockLang);
|
|
157
120
|
if (sigChanges.length > 0) {
|
|
158
|
-
diffSummary +=
|
|
159
|
-
? "\n\n### 구조적 변경 (시그니처 비교)"
|
|
160
|
-
: "\n\n### Structural changes (signature diff)";
|
|
121
|
+
diffSummary += "\n\n### Structural changes (signature diff)";
|
|
161
122
|
for (const sc of sigChanges) {
|
|
162
123
|
if (sc.type === "added") {
|
|
163
|
-
diffSummary +=
|
|
124
|
+
diffSummary += `\n+ Added: ${sc.newSignature}`;
|
|
164
125
|
}
|
|
165
126
|
else if (sc.type === "removed") {
|
|
166
|
-
diffSummary +=
|
|
127
|
+
diffSummary += `\n- Removed: ${sc.oldSignature}`;
|
|
167
128
|
}
|
|
168
129
|
else {
|
|
169
|
-
diffSummary +=
|
|
170
|
-
? `\n~ 변경: ${sc.oldSignature}\n → ${sc.newSignature}`
|
|
171
|
-
: `\n~ Changed: ${sc.oldSignature}\n → ${sc.newSignature}`;
|
|
130
|
+
diffSummary += `\n~ Changed: ${sc.oldSignature}\n → ${sc.newSignature}`;
|
|
172
131
|
}
|
|
173
132
|
}
|
|
174
133
|
}
|
|
175
134
|
}
|
|
176
135
|
if (change.newContent) {
|
|
177
136
|
const smartNew = (0, context_extractor_1.buildSmartContext)(change.newContent, codeBlockLang);
|
|
178
|
-
|
|
179
|
-
diffSummary += `\n\n${label2}\n\`\`\`${codeBlockLang}\n${smartNew}\n\`\`\``;
|
|
137
|
+
diffSummary += `\n\nFull file after modification:\n\`\`\`${codeBlockLang}\n${smartNew}\n\`\`\``;
|
|
180
138
|
}
|
|
181
139
|
}
|
|
182
|
-
const userPrompt =
|
|
183
|
-
? `## 파일 변경 감지: ${relPath}
|
|
184
|
-
변경 유형: ${change.type.toUpperCase()}
|
|
185
|
-
프로젝트 언어: ${graph.languages.join(", ") || "unknown"}
|
|
186
|
-
영향받는 파일 수: ${affectedNodes.length}
|
|
187
|
-
|
|
188
|
-
${diffSummary}
|
|
189
|
-
|
|
190
|
-
${connectedFiles.length > 0 ? `## 연결된 파일들 (${connectedFiles.length}개)\n${connectedFiles.join("\n\n")}` : "연결된 파일 없음"}
|
|
191
|
-
|
|
192
|
-
이 변경이 프로젝트에 미치는 영향을 분석하세요.`
|
|
193
|
-
: `## File change detected: ${relPath}
|
|
140
|
+
const userPrompt = `## File change detected: ${relPath}
|
|
194
141
|
Change type: ${change.type.toUpperCase()}
|
|
195
142
|
Project languages: ${graph.languages.join(", ") || "unknown"}
|
|
196
143
|
Affected files: ${affectedNodes.length}
|
|
@@ -212,7 +159,7 @@ Analyze the impact of this change on the project.`;
|
|
|
212
159
|
changeType: change.type,
|
|
213
160
|
timestamp: change.timestamp,
|
|
214
161
|
riskLevel: parsed.riskLevel || "LOW",
|
|
215
|
-
summary: parsed.summary ||
|
|
162
|
+
summary: parsed.summary || "Analysis complete",
|
|
216
163
|
brokenImports: parsed.brokenImports || [],
|
|
217
164
|
sideEffects: parsed.sideEffects || [],
|
|
218
165
|
warnings: parsed.warnings || [],
|
|
@@ -229,13 +176,11 @@ Analyze the impact of this change on the project.`;
|
|
|
229
176
|
changeType: change.type,
|
|
230
177
|
timestamp: change.timestamp,
|
|
231
178
|
riskLevel: affectedNodes.length >= 10 ? "HIGH" : affectedNodes.length >= 5 ? "MEDIUM" : "LOW",
|
|
232
|
-
summary:
|
|
233
|
-
? `AI 분석 실패 — 그래프 기반 분석: ${affectedNodes.length}개 파일 영향`
|
|
234
|
-
: `AI analysis failed — graph-based analysis: ${affectedNodes.length} files impacted`,
|
|
179
|
+
summary: `AI analysis failed — graph-based analysis: ${affectedNodes.length} files impacted`,
|
|
235
180
|
brokenImports: [],
|
|
236
181
|
sideEffects: [],
|
|
237
|
-
warnings: [
|
|
238
|
-
suggestion:
|
|
182
|
+
warnings: [`AI analysis error: ${err.message}`],
|
|
183
|
+
suggestion: "Manual review required",
|
|
239
184
|
affectedNodes,
|
|
240
185
|
analysisMs,
|
|
241
186
|
};
|
package/dist/config.d.ts
CHANGED
|
@@ -4,7 +4,6 @@ interface SykeConfig {
|
|
|
4
4
|
openaiKey?: string;
|
|
5
5
|
anthropicKey?: string;
|
|
6
6
|
aiProvider?: string;
|
|
7
|
-
language?: string;
|
|
8
7
|
port?: number;
|
|
9
8
|
}
|
|
10
9
|
/**
|
|
@@ -19,10 +18,6 @@ export declare function getAllConfig(): Record<string, string | undefined>;
|
|
|
19
18
|
* Set a config value in ~/.syke/config.json
|
|
20
19
|
*/
|
|
21
20
|
export declare function setConfig(key: keyof SykeConfig, value: string | null): void;
|
|
22
|
-
/**
|
|
23
|
-
* Detect language: config > env > system locale > default "en"
|
|
24
|
-
*/
|
|
25
|
-
export declare function getLanguage(): "ko" | "en";
|
|
26
21
|
export declare const CONFIG_DIR_PATH: string;
|
|
27
22
|
export declare const CONFIG_FILE_PATH: string;
|
|
28
23
|
export {};
|
package/dist/config.js
CHANGED
|
@@ -37,7 +37,6 @@ exports.CONFIG_FILE_PATH = exports.CONFIG_DIR_PATH = void 0;
|
|
|
37
37
|
exports.getConfig = getConfig;
|
|
38
38
|
exports.getAllConfig = getAllConfig;
|
|
39
39
|
exports.setConfig = setConfig;
|
|
40
|
-
exports.getLanguage = getLanguage;
|
|
41
40
|
/**
|
|
42
41
|
* Central config reader for SYKE MCP Server.
|
|
43
42
|
*
|
|
@@ -118,21 +117,5 @@ function setConfig(key, value) {
|
|
|
118
117
|
// ignore write errors
|
|
119
118
|
}
|
|
120
119
|
}
|
|
121
|
-
/**
|
|
122
|
-
* Detect language: config > env > system locale > default "en"
|
|
123
|
-
*/
|
|
124
|
-
function getLanguage() {
|
|
125
|
-
const configured = getConfig("language", "SYKE_LANGUAGE");
|
|
126
|
-
if (configured) {
|
|
127
|
-
return configured.startsWith("ko") ? "ko" : "en";
|
|
128
|
-
}
|
|
129
|
-
// System locale detection
|
|
130
|
-
const locale = (process.env.LANG ||
|
|
131
|
-
process.env.LC_ALL ||
|
|
132
|
-
process.env.LANGUAGE ||
|
|
133
|
-
Intl.DateTimeFormat().resolvedOptions().locale ||
|
|
134
|
-
"").toLowerCase();
|
|
135
|
-
return locale.startsWith("ko") ? "ko" : "en";
|
|
136
|
-
}
|
|
137
120
|
exports.CONFIG_DIR_PATH = CONFIG_DIR;
|
|
138
121
|
exports.CONFIG_FILE_PATH = CONFIG_FILE;
|
package/dist/index.js
CHANGED
|
@@ -124,7 +124,7 @@ async function main() {
|
|
|
124
124
|
};
|
|
125
125
|
process.on("SIGINT", shutdown);
|
|
126
126
|
process.on("SIGTERM", shutdown);
|
|
127
|
-
const server = new index_js_1.Server({ name: "syke", version: "1.4.
|
|
127
|
+
const server = new index_js_1.Server({ name: "syke", version: "1.4.16" }, { capabilities: { tools: {} } });
|
|
128
128
|
// List tools
|
|
129
129
|
server.setRequestHandler(types_js_1.ListToolsRequestSchema, async () => ({
|
|
130
130
|
tools: [
|
|
@@ -204,7 +204,7 @@ async function main() {
|
|
|
204
204
|
},
|
|
205
205
|
{
|
|
206
206
|
name: "ai_analyze",
|
|
207
|
-
description: "Use AI (Gemini/OpenAI/Claude) to perform semantic analysis on a file. Reads the file's source code and its dependents to explain what might break when modified and how to safely make changes.
|
|
207
|
+
description: "Use AI (Gemini/OpenAI/Claude) to perform semantic analysis on a file. Reads the file's source code and its dependents to explain what might break when modified and how to safely make changes.",
|
|
208
208
|
inputSchema: {
|
|
209
209
|
type: "object",
|
|
210
210
|
properties: {
|
|
@@ -488,7 +488,7 @@ async function main() {
|
|
|
488
488
|
}
|
|
489
489
|
});
|
|
490
490
|
// Pre-warm the graph (skip if no project root — e.g. Smithery scan)
|
|
491
|
-
console.error(`[syke] Starting SYKE MCP Server v1.4.
|
|
491
|
+
console.error(`[syke] Starting SYKE MCP Server v1.4.16`);
|
|
492
492
|
console.error(`[syke] License: ${licenseStatus.plan.toUpperCase()} (${licenseStatus.source})`);
|
|
493
493
|
if (licenseStatus.expiresAt) {
|
|
494
494
|
console.error(`[syke] Expires: ${licenseStatus.expiresAt}`);
|
|
@@ -660,7 +660,7 @@ main().catch((err) => {
|
|
|
660
660
|
* See: https://smithery.ai/docs/deploy#sandbox-server
|
|
661
661
|
*/
|
|
662
662
|
function createSandboxServer() {
|
|
663
|
-
const sandboxServer = new index_js_1.Server({ name: "syke", version: "1.4.
|
|
663
|
+
const sandboxServer = new index_js_1.Server({ name: "syke", version: "1.4.16" }, { capabilities: { tools: {} } });
|
|
664
664
|
sandboxServer.setRequestHandler(types_js_1.ListToolsRequestSchema, async () => ({
|
|
665
665
|
tools: [
|
|
666
666
|
{
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@syke1/mcp-server",
|
|
3
|
-
"version": "1.4.
|
|
3
|
+
"version": "1.4.16",
|
|
4
4
|
"mcpName": "io.github.khalomsky/syke",
|
|
5
5
|
"description": "AI code impact analysis MCP server — dependency graphs, cascade detection, and a mandatory build gate for AI coding agents",
|
|
6
6
|
"main": "dist/index.js",
|