Skip to content

Commit 8f99d89

Browse files
authored
Merge pull request #928 from Zy0ung/tool/feature-impact-analyzer
feat: (vibe) feature-impact-analzyer 불필요 로직 제거 및 시각화 추가, 상세 설명 추가
2 parents 632366f + 31f5b4c commit 8f99d89

3 files changed

Lines changed: 226 additions & 155 deletions

File tree

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="utf-8"/>
5+
<title>{{TITLE}}</title>
6+
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
7+
<style>
8+
body { font-family: Arial, sans-serif; margin: 20px; }
9+
h1 { margin-bottom: 5px; }
10+
.card {
11+
display: inline-block;
12+
border: 1px solid #ddd;
13+
border-radius: 6px;
14+
padding: 10px 16px;
15+
margin: 6px;
16+
background: #fafafa;
17+
}
18+
.card h3 { margin: 0 0 4px 0; font-size: 14px; color: #444; }
19+
.card .val { font-size: 18px; font-weight: bold; }
20+
table { border-collapse: collapse; width: 100%; margin-top: 10px; }
21+
th, td { border: 1px solid #ddd; padding: 6px 8px; }
22+
th { background: #f5f5f5; }
23+
td.val-right { text-align: right; }
24+
td.val-center { text-align: center; }
25+
</style>
26+
</head>
27+
<body>
28+
<h1>{{TITLE}}</h1>
29+
<div style="color:#666; font-size:14px;">{{NOTES}}</div>
30+
31+
<div class="card"><h3>Isolation (days)</h3><div class="val">{{METRICS_ISOLATION}}</div></div>
32+
<div class="card"><h3>Lag (days)</h3><div class="val">{{METRICS_LAG}}</div></div>
33+
<div class="card"><h3>Coupling (pairs)</h3><div class="val">{{METRICS_COUPLING}}</div></div>
34+
<div class="card"><h3>Scale (commits)</h3><div class="val">{{METRICS_SCALE}}</div></div>
35+
<div class="card"><h3>Dispersion (top-level dirs)</h3><div class="val">{{METRICS_DISPERSION}}</div></div>
36+
<div class="card"><h3>Chaos (%)</h3><div class="val">{{METRICS_CHAOS}}</div></div>
37+
38+
<h2 style="margin-top:18px;">Long Tail (Outliers)</h2>
39+
<table>
40+
<thead>
41+
<tr>
42+
<th>Path</th>
43+
<th style="text-align:right;">Score</th>
44+
<th style="text-align:center;">Rule</th>
45+
</tr>
46+
</thead>
47+
<tbody>
48+
{{LONG_TAIL_TABLE_ROWS}}
49+
</tbody>
50+
</table>
51+
52+
<div style="margin-top:24px;">
53+
<canvas id="ltChart" height="120"></canvas>
54+
</div>
55+
56+
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
57+
<script>
58+
const LT_LABELS = {{LONG_TAIL_LABELS_JSON}};
59+
const LT_SCORES = {{LONG_TAIL_SCORES_JSON}};
60+
61+
const ctx = document.getElementById('ltChart').getContext('2d');
62+
new Chart(ctx, {
63+
type: 'bar',
64+
data: {
65+
labels: LT_LABELS,
66+
datasets: [{
67+
label: 'Outlier Score',
68+
data: LT_SCORES,
69+
borderWidth: 1,
70+
backgroundColor: '#4e79a7'
71+
}]
72+
},
73+
options: {
74+
responsive: true,
75+
plugins: {
76+
legend: { display: true },
77+
title: { display: true, text: 'Long Tail Outliers' }
78+
},
79+
scales: {
80+
y: { beginAtZero: true }
81+
}
82+
}
83+
});
84+
</script>
85+
</body>
86+
</html>

packages/mcp/src/server.ts

Lines changed: 33 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -288,28 +288,50 @@ server.registerTool(
288288
"feature_impact_analyzer",
289289
{
290290
title: "Feature Integration Impact Analyzer",
291-
description: "Performs in-depth analysis of hidden impact of feature integration based on GitHub repository URL and PR number.",
291+
description: `
292+
Takes a GitHub repository URL, Pull Request number, and authentication token as input.
293+
Analyzes the PR’s commits and changed files to compute impact metrics — scale, dispersion,
294+
chaos, isolation, lag, and coupling — and outputs a detailed HTML report highlighting
295+
long-tail file path outliers.
296+
`.trim(),
292297
inputSchema: {
293298
repoUrl: z.string().url().describe("Full URL of GitHub repository to analyze (e.g. https://github.com/owner/repo)"),
294299
prNumber: z.number().int().positive().describe("Pull Request number to analyze"),
295300
githubToken: z.string().describe("GitHub authentication token"),
296301
locale: z.enum(["en", "ko"]).default("en").describe("Response language (en: English, ko: Korean)"),
302+
isChart: z.boolean().default(false).describe("Return HTML chart (true) or JSON (false, default)"),
297303
},
298304
},
299305

300-
async ({ repoUrl, prNumber, githubToken, locale }: FeatureImpactAnalyzerInputs & { locale?: string }) => {
306+
async ({ repoUrl, prNumber, githubToken, locale, isChart }: FeatureImpactAnalyzerInputs & { locale?: string; isChart?: boolean }) => {
301307
try {
302308
I18n.setLocale(locale || 'en');
303-
const payload = await analyzeFeatureImpact({ repoUrl, prNumber, githubToken });
309+
310+
const { McpReportGenerator } = await import("./tool/featureImpactAnalyzer.js");
311+
const analyzeFeatureImpact = new McpReportGenerator({ repoUrl, prNumber, githubToken, locale });
304312

305-
return {
306-
content: [
307-
{
308-
type: "text",
309-
text: JSON.stringify(payload, null, 2),
310-
},
311-
],
312-
};
313+
const payload = await analyzeFeatureImpact.generateWithOutlierRatings();
314+
315+
if (isChart) {
316+
const chartHtml = analyzeFeatureImpact.generateReport(payload);
317+
return {
318+
content: [
319+
{
320+
type: "text",
321+
text: JSON.stringify(payload, null, 2) + "\n created chart:" + chartHtml
322+
},
323+
],
324+
};
325+
} else {
326+
return {
327+
content: [
328+
{
329+
type: "text",
330+
text: JSON.stringify(payload, null, 2),
331+
},
332+
],
333+
};
334+
}
313335
} catch (err: any) {
314336
return {
315337
content: [

0 commit comments

Comments
 (0)