@axboot-mcp/mcp-server 1.0.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.
Files changed (78) hide show
  1. package/CLAUDE.md +119 -0
  2. package/MCP_TOOL_PLAN.md +710 -0
  3. package/MCP_USAGE.md +914 -0
  4. package/README.md +168 -0
  5. package/REPOSITORY_CONVENTIONS.md +250 -0
  6. package/SEARCH_PARAMS_MCP_TOOL_COMPLETE_PLAN.md +646 -0
  7. package/SEARCH_PARAMS_PLAN.md +2570 -0
  8. package/STORE_PATTERNS.md +1178 -0
  9. package/debug-dto.js +72 -0
  10. package/generate-banner-store.js +62 -0
  11. package/generation-plan.json +2176 -0
  12. package/generation-results.json +1817 -0
  13. package/package.json +45 -0
  14. package/scripts/batch-generate-all.js +159 -0
  15. package/scripts/batch-generate-mcp.js +329 -0
  16. package/scripts/batch-generate-stores-v2.js +272 -0
  17. package/scripts/batch-generate-stores.js +179 -0
  18. package/scripts/batch-plan.json +3810 -0
  19. package/scripts/batch-process.py +90 -0
  20. package/scripts/batch-regenerate.js +356 -0
  21. package/scripts/direct-generate.js +227 -0
  22. package/scripts/execute-batches.js +1911 -0
  23. package/scripts/generate-all-stores.js +144 -0
  24. package/scripts/generate-stores-mcp.js +161 -0
  25. package/scripts/generate-stores-v2.js +450 -0
  26. package/scripts/generate-stores-v3.js +412 -0
  27. package/scripts/generate-stores-v4.js +521 -0
  28. package/scripts/generate-stores.js +382 -0
  29. package/scripts/repos-to-process.json +1899 -0
  30. package/src/config/nh-layout-patterns.ts +166 -0
  31. package/src/docs/HOOK_GENERATION_PLAN.md +2226 -0
  32. package/src/docs/NH_STORE_PATTERNS.md +297 -0
  33. package/src/docs/README.md +216 -0
  34. package/src/docs/index.ts +28 -0
  35. package/src/docs/loader.ts +568 -0
  36. package/src/docs/patterns.json +419 -0
  37. package/src/docs/practical-examples.md +732 -0
  38. package/src/docs/quick-start.md +257 -0
  39. package/src/docs/requirements-analysis-guide.md +364 -0
  40. package/src/docs/rules.json +321 -0
  41. package/src/docs/store-pattern-analysis.md +664 -0
  42. package/src/docs/store-patterns-rules.md +1168 -0
  43. package/src/docs/store-patterns-usage-guide.md +1835 -0
  44. package/src/docs/troubleshooting.md +544 -0
  45. package/src/docs/type-selection-guide.md +572 -0
  46. package/src/docs//354/202/254/354/232/251/353/262/225/AntD-/354/273/264/355/217/254/353/204/214/355/212/270-/354/202/254/354/232/251/353/262/225.md +1515 -0
  47. package/src/docs//354/202/254/354/232/251/353/262/225/DataGrid-/354/202/254/354/232/251/353/262/225.md +866 -0
  48. package/src/docs//354/202/254/354/232/251/353/262/225/FormItem-/354/202/254/354/232/251/353/262/225.md +903 -0
  49. package/src/docs//354/202/254/354/232/251/353/262/225/FormModal-/354/202/254/354/232/251/353/262/225.md +1155 -0
  50. package/src/docs//354/202/254/354/232/251/353/262/225/MCP-/353/260/224/354/235/264/353/270/214/354/275/224/353/224/251-/352/260/200/354/235/264/353/223/234.md +1133 -0
  51. package/src/docs//354/202/254/354/232/251/353/262/225/MSW-Mock-/353/215/260/354/235/264/355/204/260-/354/202/254/354/232/251/353/262/225.md +579 -0
  52. package/src/docs//354/202/254/354/232/251/353/262/225/Search-/354/273/264/355/217/254/353/204/214/355/212/270-/354/202/254/354/232/251/353/262/225.md +738 -0
  53. package/src/docs//354/202/254/354/232/251/353/262/225/Store-/355/214/250/355/204/264-/354/202/254/354/232/251/353/262/225.md +1135 -0
  54. package/src/docs//354/202/254/354/232/251/353/262/225//355/231/224/353/251/264/352/265/254/354/204/261-/355/203/200/354/236/205/353/263/204-/352/260/234/353/260/234/354/210/234/354/204/234.md +1805 -0
  55. package/src/docs//354/202/254/354/232/251/353/262/225//355/231/224/353/251/264/355/203/200/354/236/205/353/263/204-/352/260/234/353/260/234-/355/224/204/353/241/254/355/224/204/355/212/270-/352/260/200/354/235/264/353/223/234.md +946 -0
  56. package/src/docs//354/202/254/354/232/251/353/262/225//355/231/225/354/236/245/355/231/224/353/251/264/355/203/200/354/236/205/353/263/204-/354/203/201/354/204/270-/355/224/204/353/241/254/355/224/204/355/212/270/352/260/200/354/235/264/353/223/234.md +2422 -0
  57. package/src/features/store-features.ts +232 -0
  58. package/src/handlers/analyze-requirements.ts +403 -0
  59. package/src/handlers/analyze.ts +1373 -0
  60. package/src/handlers/generate-from-requirements.ts +250 -0
  61. package/src/handlers/generate-hook.ts +950 -0
  62. package/src/handlers/generate-interactive.ts +840 -0
  63. package/src/handlers/generate-listdatagrid.ts +521 -0
  64. package/src/handlers/generate-multi-stores.ts +577 -0
  65. package/src/handlers/generate-requirements-from-layout.ts +160 -0
  66. package/src/handlers/generate-search-params.ts +717 -0
  67. package/src/handlers/generate.ts +911 -0
  68. package/src/handlers/list-templates.ts +104 -0
  69. package/src/handlers/scan-metadata.ts +485 -0
  70. package/src/handlers/suggest-layout.ts +326 -0
  71. package/src/index.ts +959 -0
  72. package/src/prompts/search-params.md +793 -0
  73. package/src/templates/index.ts +107 -0
  74. package/src/templates/unified.ts +462 -0
  75. package/store-generation-error-patterns.md +225 -0
  76. package/test/useAgentStore.ts +136 -0
  77. package/test-server.js +78 -0
  78. package/tsconfig.json +20 -0
@@ -0,0 +1,326 @@
1
+ import { analyzeInterface } from './analyze.js';
2
+ import { NH_LAYOUT_PATTERNS, getNHLayoutPattern } from '../config/nh-layout-patterns.js';
3
+
4
+ /**
5
+ * 레이아웃 매칭 점수 결과
6
+ */
7
+ export interface LayoutMatch {
8
+ layoutType: string;
9
+ layoutName: string;
10
+ matchScore: number;
11
+ matchReasons: string[];
12
+ }
13
+
14
+ /**
15
+ * 레이아웃 추천 결과
16
+ */
17
+ export interface LayoutSuggestionResult {
18
+ success: boolean;
19
+ repositoryInfo: {
20
+ className: string;
21
+ serviceName: string;
22
+ methodCount: number;
23
+ methods: Array<{
24
+ name: string;
25
+ description: string;
26
+ }>;
27
+ };
28
+ analysis: {
29
+ hasTreeMethods: boolean;
30
+ hasListMethods: boolean;
31
+ hasDetailMethods: boolean;
32
+ hasSaveMethods: boolean;
33
+ hasDeleteMethods: boolean;
34
+ hasSummaryMethods: boolean;
35
+ hasStatMethods: boolean;
36
+ listMethodCount: number;
37
+ hasMultipleLists: boolean;
38
+ methodNames: string[];
39
+ };
40
+ suggestions: LayoutMatch[];
41
+ topRecommendation?: LayoutMatch;
42
+ }
43
+
44
+ /**
45
+ * Repository 분석 결과 기반 NH 레이아웃 패턴 추천
46
+ */
47
+ export async function suggestLayout(args: {
48
+ interfacePath: string;
49
+ }): Promise<{
50
+ content: Array<{ type: string; text: string }>;
51
+ }> {
52
+ const { interfacePath } = args;
53
+
54
+ try {
55
+ // 1. Repository 분석
56
+ const analyzeResult = await analyzeInterface({ interfacePath });
57
+ const analyzeData = JSON.parse(analyzeResult.content[0].text);
58
+
59
+ if (!analyzeData.success) {
60
+ return {
61
+ content: [
62
+ {
63
+ type: 'text',
64
+ text: JSON.stringify({
65
+ success: false,
66
+ error: analyzeData.error || 'Repository 분석 실패',
67
+ }),
68
+ },
69
+ ],
70
+ };
71
+ }
72
+
73
+ // 2. Repository 특징 분석
74
+ const analysis = analyzeRepository(analyzeData);
75
+
76
+ // 3. 각 레이아웃 패턴과 매칭
77
+ const suggestions = matchLayoutPatterns(analysis);
78
+
79
+ // 4. 상위 추천 선택
80
+ const topRecommendation = suggestions.length > 0 ? suggestions[0] : undefined;
81
+
82
+ // 5. 결과 반환
83
+ const result: LayoutSuggestionResult = {
84
+ success: true,
85
+ repositoryInfo: {
86
+ className: analyzeData.className,
87
+ serviceName: analyzeData.serviceName,
88
+ methodCount: analyzeData.methods.length,
89
+ methods: analyzeData.methods.map((m: any) => ({
90
+ name: m.name,
91
+ description: m.description || '',
92
+ })),
93
+ },
94
+ analysis,
95
+ suggestions,
96
+ topRecommendation,
97
+ };
98
+
99
+ return {
100
+ content: [
101
+ {
102
+ type: 'text',
103
+ text: JSON.stringify(result, null, 2),
104
+ },
105
+ ],
106
+ };
107
+ } catch (error) {
108
+ return {
109
+ content: [
110
+ {
111
+ type: 'text',
112
+ text: JSON.stringify({
113
+ success: false,
114
+ error: error instanceof Error ? error.message : String(error),
115
+ }),
116
+ },
117
+ ],
118
+ };
119
+ }
120
+ }
121
+
122
+ /**
123
+ * Repository 특징 분석
124
+ */
125
+ function analyzeRepository(analyzeData: any): LayoutSuggestionResult['analysis'] {
126
+ const methods = analyzeData.methods || [];
127
+
128
+ const methodNames = methods.map((m: any) => m.name?.toLowerCase() || '');
129
+
130
+ const listCount = methodNames.filter((n: string) => n.includes('list')).length;
131
+
132
+ return {
133
+ hasTreeMethods:
134
+ methodNames.some((n: string) => n.includes('tree')) || methodNames.some((n: string) => n.includes('node')),
135
+ hasListMethods: listCount > 0,
136
+ hasDetailMethods: methodNames.some((n: string) => n.includes('detail')),
137
+ hasSaveMethods: methodNames.some((n: string) => n.includes('save')) || methodNames.some((n: string) => n.includes('insert')),
138
+ hasDeleteMethods: methodNames.some((n: string) => n.includes('delete')) || methodNames.some((n: string) => n.includes('remove')),
139
+ hasSummaryMethods: methodNames.some((n: string) => n.includes('summary')),
140
+ hasStatMethods:
141
+ methodNames.some((n: string) => n.includes('stat')) ||
142
+ methodNames.some((n: string) => n.includes('dashboard')) ||
143
+ methodNames.some((n: string) => n.includes('chart')),
144
+ listMethodCount: listCount,
145
+ hasMultipleLists: listCount >= 2,
146
+ methodNames,
147
+ };
148
+ }
149
+
150
+ /**
151
+ * 레이아웃 패턴 매칭
152
+ */
153
+ function matchLayoutPatterns(analysis: LayoutSuggestionResult['analysis']): LayoutMatch[] {
154
+ const matches: LayoutMatch[] = [];
155
+
156
+ // 각 레이아웃 패턴별 매칭 점수 계산
157
+ for (const [layoutType, layout] of Object.entries(NH_LAYOUT_PATTERNS)) {
158
+ const matchResult = calculateMatchScore(layoutType, layout, analysis);
159
+ matches.push(matchResult);
160
+ }
161
+
162
+ // 매칭 점수순 정렬
163
+ return matches.sort((a, b) => b.matchScore - a.matchScore);
164
+ }
165
+
166
+ /**
167
+ * 매칭 점수 계산
168
+ */
169
+ function calculateMatchScore(
170
+ layoutType: string,
171
+ layout: { type: string; name: string; description: string },
172
+ analysis: LayoutSuggestionResult['analysis']
173
+ ): LayoutMatch {
174
+ let score = 0;
175
+ const reasons: string[] = [];
176
+
177
+ // LEFT_DETAIL_FORM: 트리 + 저장
178
+ if (layoutType === 'LEFT_DETAIL_FORM') {
179
+ if (analysis.hasTreeMethods) {
180
+ score += 10;
181
+ reasons.push('트리 메서드 감지됨');
182
+ }
183
+ if (analysis.hasSaveMethods) {
184
+ score += 5;
185
+ reasons.push('저장 메서드 감지됨');
186
+ }
187
+ if (analysis.hasListMethods && analysis.listMethodCount === 1) {
188
+ score += 3;
189
+ reasons.push('단일 목록 메서드');
190
+ }
191
+ }
192
+
193
+ // LEFT_DETAIL_LIST: 다중 목록 (좌-우 Master-Detail)
194
+ else if (layoutType === 'LEFT_DETAIL_LIST') {
195
+ if (analysis.hasMultipleLists) {
196
+ const listCount = analysis.listMethodCount;
197
+ if (listCount === 2) {
198
+ score += 12; // 2개의 list 메서드 = Master-Detail 패턴
199
+ reasons.push('2개의 목록 메서드 (Master-Detail 패턴)');
200
+ } else if (listCount >= 3) {
201
+ score += 10;
202
+ reasons.push('3개 이상의 목록 메서드');
203
+ } else {
204
+ score += 8;
205
+ reasons.push('다중 목록 메서드 감지됨');
206
+ }
207
+ }
208
+ if (analysis.hasDetailMethods) {
209
+ score += 5;
210
+ reasons.push('상세 메서드 감지됨');
211
+ }
212
+ // 그룹 관련 메서드가 있으면 추가 점수
213
+ if (analysis.methodNames.some((n: string) => n.includes('group'))) {
214
+ score += 3;
215
+ reasons.push('그룹 관련 메서드 감지됨 (Master)');
216
+ }
217
+ }
218
+
219
+ // MULTI_PANEL: 복잡한 다중 패널
220
+ else if (layoutType === 'MULTI_PANEL') {
221
+ if (analysis.hasMultipleLists && analysis.listMethodCount >= 3) {
222
+ score += 10;
223
+ reasons.push('3개 이상의 목록 메서드');
224
+ }
225
+ if (analysis.hasDetailMethods) {
226
+ score += 3;
227
+ reasons.push('상세 메서드 포함');
228
+ }
229
+ if (analysis.hasSaveMethods) {
230
+ score += 2;
231
+ reasons.push('저장 메서드 포함');
232
+ }
233
+ }
234
+
235
+ // LIST_DRAWER: 단일 목록 + 상세 (Drawer)
236
+ else if (layoutType === 'LIST_DRAWER') {
237
+ if (analysis.hasListMethods && analysis.listMethodCount === 1) {
238
+ score += 8;
239
+ reasons.push('단일 목록 메서드');
240
+ }
241
+ if (analysis.hasDetailMethods) {
242
+ score += 7;
243
+ reasons.push('상세 메서드 감지됨 (Drawer용)');
244
+ }
245
+ if (!analysis.hasSaveMethods) {
246
+ score += 2;
247
+ reasons.push('저장 메서드 없음 (조회 전용)');
248
+ }
249
+ }
250
+
251
+ // LIST_MODAL: 단일 목록 + CRUD (가장 일반적)
252
+ else if (layoutType === 'LIST_MODAL') {
253
+ if (analysis.hasListMethods && analysis.listMethodCount === 1) {
254
+ score += 7;
255
+ reasons.push('단일 목록 메서드');
256
+ }
257
+ if (analysis.hasSaveMethods) {
258
+ score += 5;
259
+ reasons.push('저장 메서드 감지됨');
260
+ }
261
+ if (analysis.hasDeleteMethods) {
262
+ score += 3;
263
+ reasons.push('삭제 메서드 감지됨');
264
+ }
265
+ // 기본 점수 (가장 일반적인 패턴)
266
+ score += 2;
267
+ reasons.push('가장 일반적인 패턴');
268
+ }
269
+
270
+ // TAB_BASED: 탭 기반
271
+ else if (layoutType === 'TAB_BASED') {
272
+ if (analysis.hasMultipleLists) {
273
+ score += 8;
274
+ reasons.push('다중 목록 (탭별)');
275
+ }
276
+ // 탭 관련 키워드는 메서드 이름으로 잘 안 나오므로 기본 점수 낮음
277
+ score += 1;
278
+ }
279
+
280
+ // LIST_SUMMARY: 목록 + 요약
281
+ else if (layoutType === 'LIST_SUMMARY') {
282
+ if (analysis.hasListMethods) {
283
+ score += 6;
284
+ reasons.push('목록 메서드 감지됨');
285
+ }
286
+ if (analysis.hasSummaryMethods || analysis.hasStatMethods) {
287
+ score += 8;
288
+ reasons.push('요약/통계 메서드 감지됨');
289
+ }
290
+ }
291
+
292
+ // DASHBOARD: 대시보드만
293
+ else if (layoutType === 'DASHBOARD') {
294
+ if (!analysis.hasListMethods) {
295
+ score += 10;
296
+ reasons.push('목록 메서드 없음');
297
+ }
298
+ if (analysis.hasStatMethods || analysis.hasSummaryMethods) {
299
+ score += 8;
300
+ reasons.push('통계/요약 메서드 감지됨');
301
+ }
302
+ }
303
+
304
+ // FORM_ONLY: 폼만
305
+ else if (layoutType === 'FORM_ONLY') {
306
+ if (!analysis.hasListMethods) {
307
+ score += 8;
308
+ reasons.push('목록 메서드 없음');
309
+ }
310
+ if (analysis.hasSaveMethods) {
311
+ score += 7;
312
+ reasons.push('저장 메서드만 존재');
313
+ }
314
+ }
315
+
316
+ // 점수 정규화 (0-100)
317
+ const maxScore = 20;
318
+ const normalizedScore = Math.min(100, Math.round((score / maxScore) * 100));
319
+
320
+ return {
321
+ layoutType: layout.type,
322
+ layoutName: layout.name,
323
+ matchScore: normalizedScore,
324
+ matchReasons: reasons.length > 0 ? reasons : ['기본 매칭'],
325
+ };
326
+ }