@mandujs/mcp 0.12.1 → 0.13.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 (141) hide show
  1. package/README.md +367 -367
  2. package/package.json +2 -2
  3. package/src/activity-monitor.ts +847 -847
  4. package/src/adapters/index.ts +20 -20
  5. package/src/adapters/monitor-adapter.ts +100 -100
  6. package/src/adapters/tool-adapter.ts +88 -88
  7. package/src/executor/error-handler.ts +250 -250
  8. package/src/executor/index.ts +22 -22
  9. package/src/executor/tool-executor.ts +148 -148
  10. package/src/hooks/config-watcher.ts +174 -174
  11. package/src/hooks/index.ts +23 -23
  12. package/src/hooks/mcp-hooks.ts +227 -227
  13. package/src/index.ts +106 -106
  14. package/src/logging/index.ts +15 -15
  15. package/src/logging/mcp-transport.ts +134 -134
  16. package/src/registry/index.ts +13 -13
  17. package/src/registry/mcp-tool-registry.ts +298 -298
  18. package/src/resources/skills/guides.ts +1136 -1136
  19. package/src/resources/skills/index.ts +12 -12
  20. package/src/resources/skills/loader.ts +218 -218
  21. package/src/resources/skills/mandu-composition/SKILL.md +91 -91
  22. package/src/resources/skills/mandu-composition/metadata.json +13 -13
  23. package/src/resources/skills/mandu-composition/rules/_sections.md +26 -26
  24. package/src/resources/skills/mandu-composition/rules/_template.md +77 -77
  25. package/src/resources/skills/mandu-composition/rules/comp-arch-avoid-boolean-props.md +146 -146
  26. package/src/resources/skills/mandu-composition/rules/comp-arch-compound-components.md +164 -164
  27. package/src/resources/skills/mandu-composition/rules/comp-island-event.md +161 -161
  28. package/src/resources/skills/mandu-composition/rules/comp-island-slot-split.md +167 -167
  29. package/src/resources/skills/mandu-composition/rules/comp-pattern-children.md +149 -149
  30. package/src/resources/skills/mandu-composition/rules/comp-state-context-interface.md +148 -148
  31. package/src/resources/skills/mandu-composition/rules/comp-state-lift-state.md +150 -150
  32. package/src/resources/skills/mandu-deployment/SKILL.md +92 -92
  33. package/src/resources/skills/mandu-deployment/_sections.md +41 -41
  34. package/src/resources/skills/mandu-deployment/_template.md +38 -38
  35. package/src/resources/skills/mandu-deployment/metadata.json +13 -13
  36. package/src/resources/skills/mandu-deployment/rules/deploy-build-bun.md +109 -109
  37. package/src/resources/skills/mandu-deployment/rules/deploy-build-output.md +115 -115
  38. package/src/resources/skills/mandu-deployment/rules/deploy-cicd-github.md +219 -219
  39. package/src/resources/skills/mandu-deployment/rules/deploy-docker-bun.md +150 -150
  40. package/src/resources/skills/mandu-deployment/rules/deploy-docker-compose.md +223 -223
  41. package/src/resources/skills/mandu-deployment/rules/deploy-platform-fly.md +152 -152
  42. package/src/resources/skills/mandu-deployment/rules/deploy-platform-render.md +179 -179
  43. package/src/resources/skills/mandu-deployment/rules/deploy-platform-supabase.md +323 -323
  44. package/src/resources/skills/mandu-deployment/rules/deploy-platform-vercel.md +140 -140
  45. package/src/resources/skills/mandu-fs-routes/SKILL.md +82 -82
  46. package/src/resources/skills/mandu-fs-routes/metadata.json +12 -12
  47. package/src/resources/skills/mandu-fs-routes/rules/_sections.md +36 -36
  48. package/src/resources/skills/mandu-fs-routes/rules/_template.md +69 -69
  49. package/src/resources/skills/mandu-fs-routes/rules/routes-api-methods.md +65 -65
  50. package/src/resources/skills/mandu-fs-routes/rules/routes-dynamic-param.md +93 -93
  51. package/src/resources/skills/mandu-fs-routes/rules/routes-naming-page.md +55 -55
  52. package/src/resources/skills/mandu-guard/SKILL.md +129 -129
  53. package/src/resources/skills/mandu-guard/metadata.json +12 -12
  54. package/src/resources/skills/mandu-guard/rules/_sections.md +36 -36
  55. package/src/resources/skills/mandu-guard/rules/_template.md +82 -82
  56. package/src/resources/skills/mandu-guard/rules/guard-config-rules.md +100 -100
  57. package/src/resources/skills/mandu-guard/rules/guard-layer-direction.md +76 -76
  58. package/src/resources/skills/mandu-guard/rules/guard-preset-mandu.md +81 -81
  59. package/src/resources/skills/mandu-guard/rules/guard-validate-import.md +80 -80
  60. package/src/resources/skills/mandu-hydration/SKILL.md +91 -91
  61. package/src/resources/skills/mandu-hydration/metadata.json +12 -12
  62. package/src/resources/skills/mandu-hydration/rules/_sections.md +31 -31
  63. package/src/resources/skills/mandu-hydration/rules/_template.md +72 -72
  64. package/src/resources/skills/mandu-hydration/rules/hydration-data-event.md +109 -109
  65. package/src/resources/skills/mandu-hydration/rules/hydration-directive-use-client.md +55 -55
  66. package/src/resources/skills/mandu-hydration/rules/hydration-island-setup.md +113 -113
  67. package/src/resources/skills/mandu-hydration/rules/hydration-priority-visible.md +68 -68
  68. package/src/resources/skills/mandu-performance/SKILL.md +85 -85
  69. package/src/resources/skills/mandu-performance/metadata.json +14 -14
  70. package/src/resources/skills/mandu-performance/rules/_sections.md +31 -31
  71. package/src/resources/skills/mandu-performance/rules/_template.md +64 -64
  72. package/src/resources/skills/mandu-performance/rules/perf-async-defer-await.md +103 -103
  73. package/src/resources/skills/mandu-performance/rules/perf-async-parallel.md +95 -95
  74. package/src/resources/skills/mandu-performance/rules/perf-bun-file.md +124 -124
  75. package/src/resources/skills/mandu-performance/rules/perf-bun-serve.md +125 -125
  76. package/src/resources/skills/mandu-performance/rules/perf-bundle-imports.md +80 -80
  77. package/src/resources/skills/mandu-performance/rules/perf-bundle-island-lazy.md +145 -145
  78. package/src/resources/skills/mandu-performance/rules/perf-cache-react.md +98 -98
  79. package/src/resources/skills/mandu-performance/rules/perf-render-transitions.md +154 -154
  80. package/src/resources/skills/mandu-security/SKILL.md +87 -87
  81. package/src/resources/skills/mandu-security/metadata.json +13 -13
  82. package/src/resources/skills/mandu-security/rules/_sections.md +31 -31
  83. package/src/resources/skills/mandu-security/rules/_template.md +74 -74
  84. package/src/resources/skills/mandu-security/rules/sec-auth-guard.md +127 -127
  85. package/src/resources/skills/mandu-security/rules/sec-env-management.md +133 -133
  86. package/src/resources/skills/mandu-security/rules/sec-input-validate.md +148 -148
  87. package/src/resources/skills/mandu-security/rules/sec-protect-csrf.md +146 -146
  88. package/src/resources/skills/mandu-security/rules/sec-protect-headers.md +138 -138
  89. package/src/resources/skills/mandu-slot/SKILL.md +85 -85
  90. package/src/resources/skills/mandu-slot/metadata.json +12 -12
  91. package/src/resources/skills/mandu-slot/rules/_sections.md +36 -36
  92. package/src/resources/skills/mandu-slot/rules/_template.md +63 -63
  93. package/src/resources/skills/mandu-slot/rules/slot-basic-structure.md +38 -38
  94. package/src/resources/skills/mandu-slot/rules/slot-ctx-response.md +56 -56
  95. package/src/resources/skills/mandu-slot/rules/slot-guard-auth.md +59 -59
  96. package/src/resources/skills/mandu-slot/rules/slot-http-methods.md +64 -64
  97. package/src/resources/skills/mandu-styling/SKILL.md +154 -154
  98. package/src/resources/skills/mandu-styling/_sections.md +43 -43
  99. package/src/resources/skills/mandu-styling/_template.md +32 -32
  100. package/src/resources/skills/mandu-styling/metadata.json +15 -15
  101. package/src/resources/skills/mandu-styling/rules/style-component-compound.md +235 -235
  102. package/src/resources/skills/mandu-styling/rules/style-component-slots.md +255 -255
  103. package/src/resources/skills/mandu-styling/rules/style-component-tokens.md +205 -205
  104. package/src/resources/skills/mandu-styling/rules/style-island-animations.md +272 -272
  105. package/src/resources/skills/mandu-styling/rules/style-island-scoping.md +167 -167
  106. package/src/resources/skills/mandu-styling/rules/style-island-variants.md +221 -221
  107. package/src/resources/skills/mandu-styling/rules/style-perf-critical.md +209 -209
  108. package/src/resources/skills/mandu-styling/rules/style-perf-purge.md +192 -192
  109. package/src/resources/skills/mandu-styling/rules/style-setup-modules.md +162 -162
  110. package/src/resources/skills/mandu-styling/rules/style-setup-panda.md +164 -164
  111. package/src/resources/skills/mandu-styling/rules/style-setup-tailwind.md +170 -170
  112. package/src/resources/skills/mandu-styling/rules/style-tailwind-v4-gotchas.md +179 -179
  113. package/src/resources/skills/mandu-styling/rules/style-theme-darkmode.md +229 -229
  114. package/src/resources/skills/mandu-testing/SKILL.md +99 -99
  115. package/src/resources/skills/mandu-testing/metadata.json +13 -13
  116. package/src/resources/skills/mandu-testing/rules/_sections.md +26 -26
  117. package/src/resources/skills/mandu-testing/rules/_template.md +65 -65
  118. package/src/resources/skills/mandu-testing/rules/test-component-island.md +195 -195
  119. package/src/resources/skills/mandu-testing/rules/test-e2e-playwright.md +196 -196
  120. package/src/resources/skills/mandu-testing/rules/test-mock-fetch.md +219 -219
  121. package/src/resources/skills/mandu-testing/rules/test-slot-unit.md +192 -192
  122. package/src/resources/skills/mandu-ui/SKILL.md +117 -117
  123. package/src/resources/skills/mandu-ui/_sections.md +23 -23
  124. package/src/resources/skills/mandu-ui/_template.md +32 -32
  125. package/src/resources/skills/mandu-ui/metadata.json +13 -13
  126. package/src/resources/skills/mandu-ui/rules/ui-accessibility-aria.md +232 -232
  127. package/src/resources/skills/mandu-ui/rules/ui-accessibility-focus.md +238 -238
  128. package/src/resources/skills/mandu-ui/rules/ui-composition-patterns.md +259 -259
  129. package/src/resources/skills/mandu-ui/rules/ui-island-integration.md +258 -258
  130. package/src/resources/skills/mandu-ui/rules/ui-radix-patterns.md +213 -213
  131. package/src/resources/skills/mandu-ui/rules/ui-shadcn-setup.md +209 -209
  132. package/src/resources/skills/recipes.ts +932 -932
  133. package/src/tools/generate.ts +7 -4
  134. package/src/tools/guard.ts +17 -4
  135. package/src/tools/hydration.ts +10 -10
  136. package/src/tools/project.ts +334 -334
  137. package/src/tools/runtime.ts +497 -497
  138. package/src/tools/seo.ts +417 -417
  139. package/src/tools/spec.ts +80 -159
  140. package/src/utils/project.ts +22 -12
  141. package/src/utils/withWarnings.ts +83 -83
@@ -1,250 +1,250 @@
1
- /**
2
- * MCP Error Handler
3
- *
4
- * DNA-007 에러 추출 시스템 기반 MCP 에러 처리
5
- */
6
-
7
- import {
8
- extractErrorInfo,
9
- classifyError,
10
- serializeError,
11
- isRetryableError,
12
- type ErrorCategory,
13
- type ExtractedErrorInfo,
14
- } from "@mandujs/core";
15
-
16
- /**
17
- * MCP 에러 응답 타입
18
- */
19
- export interface McpErrorResponse {
20
- /** 에러 메시지 */
21
- error: string;
22
- /** 에러 코드 (있는 경우) */
23
- code?: string;
24
- /** 에러 카테고리 (DNA-007) */
25
- category: ErrorCategory;
26
- /** 재시도 가능 여부 */
27
- retryable: boolean;
28
- /** 추가 컨텍스트 */
29
- context?: Record<string, unknown>;
30
- /** 복구 제안 */
31
- suggestion?: string;
32
- }
33
-
34
- /**
35
- * MCP 도구 응답 타입
36
- */
37
- export interface McpToolResponse {
38
- content: Array<{ type: string; text: string }>;
39
- isError?: boolean;
40
- }
41
-
42
- /**
43
- * 에러를 MCP 응답 형식으로 변환
44
- *
45
- * @example
46
- * ```ts
47
- * try {
48
- * await tool.execute(args);
49
- * } catch (err) {
50
- * const response = formatMcpError(err, "mandu_guard_check");
51
- * // { error: "...", code: "...", category: "validation", ... }
52
- * }
53
- * ```
54
- */
55
- export function formatMcpError(err: unknown, toolName?: string): McpErrorResponse {
56
- const info = extractErrorInfo(err);
57
-
58
- return {
59
- error: info.message,
60
- code: info.code,
61
- category: info.category,
62
- retryable: isRetryableError(err),
63
- context: {
64
- ...info.context,
65
- toolName,
66
- errorName: info.name,
67
- },
68
- suggestion: generateSuggestion(info, toolName),
69
- };
70
- }
71
-
72
- /**
73
- * 에러 카테고리 및 도구별 복구 제안 생성
74
- */
75
- function generateSuggestion(info: ExtractedErrorInfo, toolName?: string): string | undefined {
76
- // 도구별 특화 제안
77
- if (toolName) {
78
- const toolSuggestion = getToolSpecificSuggestion(toolName, info);
79
- if (toolSuggestion) return toolSuggestion;
80
- }
81
-
82
- // 카테고리별 일반 제안
83
- switch (info.category) {
84
- case "network":
85
- return "네트워크 연결을 확인하고 다시 시도해주세요.";
86
-
87
- case "timeout":
88
- return "요청 시간이 초과되었습니다. 잠시 후 다시 시도해주세요.";
89
-
90
- case "auth":
91
- return "인증 정보를 확인해주세요.";
92
-
93
- case "validation":
94
- return "입력 값을 확인해주세요. 필수 파라미터가 누락되었거나 형식이 올바르지 않을 수 있습니다.";
95
-
96
- case "config":
97
- return "설정 파일(mandu.config.ts)을 확인해주세요.";
98
-
99
- case "system":
100
- if (info.code === "ENOENT") {
101
- const path = info.context?.path ?? "unknown";
102
- return `파일 또는 디렉토리를 찾을 수 없습니다: ${path}`;
103
- }
104
- if (info.code === "EACCES" || info.code === "EPERM") {
105
- return "파일 접근 권한을 확인해주세요.";
106
- }
107
- return "시스템 리소스를 확인해주세요.";
108
-
109
- case "external":
110
- return "외부 서비스에 문제가 있습니다. 잠시 후 다시 시도해주세요.";
111
-
112
- case "internal":
113
- return "내부 오류가 발생했습니다. 문제가 지속되면 이슈를 보고해주세요.";
114
-
115
- default:
116
- return undefined;
117
- }
118
- }
119
-
120
- /**
121
- * 도구별 특화된 에러 제안
122
- */
123
- function getToolSpecificSuggestion(toolName: string, info: ExtractedErrorInfo): string | undefined {
124
- // spec 관련 도구
125
- if (toolName.startsWith("mandu_") && toolName.includes("route")) {
126
- if (info.code === "ENOENT") {
127
- return "routes.manifest.json 파일이 없습니다. `mandu init`을 먼저 실행해주세요.";
128
- }
129
- if (info.message.includes("not found")) {
130
- return "해당 라우트를 찾을 수 없습니다. `mandu_list_routes`로 존재하는 라우트를 확인해주세요.";
131
- }
132
- }
133
-
134
- // guard 관련 도구
135
- if (toolName === "mandu_guard_check") {
136
- if (info.category === "config") {
137
- return "Guard 설정을 확인해주세요. mandu.config.ts의 guard 섹션을 검토해주세요.";
138
- }
139
- }
140
-
141
- // contract 관련 도구
142
- if (toolName.includes("contract")) {
143
- if (info.category === "validation") {
144
- return "Contract 스키마가 올바른지 확인해주세요. Zod 스키마 문법을 확인해주세요.";
145
- }
146
- }
147
-
148
- // generate 관련 도구
149
- if (toolName === "mandu_generate") {
150
- if (info.code === "EEXIST") {
151
- return "파일이 이미 존재합니다. 덮어쓰려면 force 옵션을 사용해주세요.";
152
- }
153
- }
154
-
155
- // transaction 관련 도구
156
- if (toolName.includes("tx") || toolName.includes("transaction")) {
157
- if (info.message.includes("no active")) {
158
- return "활성화된 트랜잭션이 없습니다. `mandu_begin`으로 트랜잭션을 시작해주세요.";
159
- }
160
- }
161
-
162
- return undefined;
163
- }
164
-
165
- /**
166
- * 도구 실행 결과를 MCP 응답으로 변환
167
- *
168
- * @example
169
- * ```ts
170
- * // 성공 응답
171
- * const response = createToolResponse("mandu_list_routes", { routes: [...] });
172
- *
173
- * // 에러 응답
174
- * const response = createToolResponse("mandu_list_routes", null, new Error("..."));
175
- * ```
176
- */
177
- export function createToolResponse(
178
- toolName: string,
179
- result: unknown,
180
- error?: unknown
181
- ): McpToolResponse {
182
- if (error) {
183
- const errorResponse = formatMcpError(error, toolName);
184
- return {
185
- content: [
186
- {
187
- type: "text",
188
- text: JSON.stringify(errorResponse, null, 2),
189
- },
190
- ],
191
- isError: true,
192
- };
193
- }
194
-
195
- return {
196
- content: [
197
- {
198
- type: "text",
199
- text: JSON.stringify(result, null, 2),
200
- },
201
- ],
202
- };
203
- }
204
-
205
- /**
206
- * 에러 응답인지 확인
207
- */
208
- export function isErrorResponse(response: McpToolResponse): boolean {
209
- return response.isError === true;
210
- }
211
-
212
- /**
213
- * 에러 응답에서 McpErrorResponse 추출
214
- */
215
- export function extractErrorFromResponse(response: McpToolResponse): McpErrorResponse | null {
216
- if (!response.isError) return null;
217
-
218
- try {
219
- const text = response.content[0]?.text;
220
- if (!text) return null;
221
- return JSON.parse(text) as McpErrorResponse;
222
- } catch {
223
- return null;
224
- }
225
- }
226
-
227
- /**
228
- * 에러 로깅 헬퍼
229
- */
230
- export function logToolError(
231
- toolName: string,
232
- error: unknown,
233
- args?: Record<string, unknown>
234
- ): void {
235
- const info = extractErrorInfo(error);
236
-
237
- console.error(`[MCP:${toolName}] ${info.category.toUpperCase()}: ${info.message}`);
238
-
239
- if (info.code) {
240
- console.error(` Code: ${info.code}`);
241
- }
242
-
243
- if (args && Object.keys(args).length > 0) {
244
- console.error(` Args:`, JSON.stringify(args, null, 2));
245
- }
246
-
247
- if (info.context && Object.keys(info.context).length > 0) {
248
- console.error(` Context:`, info.context);
249
- }
250
- }
1
+ /**
2
+ * MCP Error Handler
3
+ *
4
+ * DNA-007 에러 추출 시스템 기반 MCP 에러 처리
5
+ */
6
+
7
+ import {
8
+ extractErrorInfo,
9
+ classifyError,
10
+ serializeError,
11
+ isRetryableError,
12
+ type ErrorCategory,
13
+ type ExtractedErrorInfo,
14
+ } from "@mandujs/core";
15
+
16
+ /**
17
+ * MCP 에러 응답 타입
18
+ */
19
+ export interface McpErrorResponse {
20
+ /** 에러 메시지 */
21
+ error: string;
22
+ /** 에러 코드 (있는 경우) */
23
+ code?: string;
24
+ /** 에러 카테고리 (DNA-007) */
25
+ category: ErrorCategory;
26
+ /** 재시도 가능 여부 */
27
+ retryable: boolean;
28
+ /** 추가 컨텍스트 */
29
+ context?: Record<string, unknown>;
30
+ /** 복구 제안 */
31
+ suggestion?: string;
32
+ }
33
+
34
+ /**
35
+ * MCP 도구 응답 타입
36
+ */
37
+ export interface McpToolResponse {
38
+ content: Array<{ type: string; text: string }>;
39
+ isError?: boolean;
40
+ }
41
+
42
+ /**
43
+ * 에러를 MCP 응답 형식으로 변환
44
+ *
45
+ * @example
46
+ * ```ts
47
+ * try {
48
+ * await tool.execute(args);
49
+ * } catch (err) {
50
+ * const response = formatMcpError(err, "mandu_guard_check");
51
+ * // { error: "...", code: "...", category: "validation", ... }
52
+ * }
53
+ * ```
54
+ */
55
+ export function formatMcpError(err: unknown, toolName?: string): McpErrorResponse {
56
+ const info = extractErrorInfo(err);
57
+
58
+ return {
59
+ error: info.message,
60
+ code: info.code,
61
+ category: info.category,
62
+ retryable: isRetryableError(err),
63
+ context: {
64
+ ...info.context,
65
+ toolName,
66
+ errorName: info.name,
67
+ },
68
+ suggestion: generateSuggestion(info, toolName),
69
+ };
70
+ }
71
+
72
+ /**
73
+ * 에러 카테고리 및 도구별 복구 제안 생성
74
+ */
75
+ function generateSuggestion(info: ExtractedErrorInfo, toolName?: string): string | undefined {
76
+ // 도구별 특화 제안
77
+ if (toolName) {
78
+ const toolSuggestion = getToolSpecificSuggestion(toolName, info);
79
+ if (toolSuggestion) return toolSuggestion;
80
+ }
81
+
82
+ // 카테고리별 일반 제안
83
+ switch (info.category) {
84
+ case "network":
85
+ return "네트워크 연결을 확인하고 다시 시도해주세요.";
86
+
87
+ case "timeout":
88
+ return "요청 시간이 초과되었습니다. 잠시 후 다시 시도해주세요.";
89
+
90
+ case "auth":
91
+ return "인증 정보를 확인해주세요.";
92
+
93
+ case "validation":
94
+ return "입력 값을 확인해주세요. 필수 파라미터가 누락되었거나 형식이 올바르지 않을 수 있습니다.";
95
+
96
+ case "config":
97
+ return "설정 파일(mandu.config.ts)을 확인해주세요.";
98
+
99
+ case "system":
100
+ if (info.code === "ENOENT") {
101
+ const path = info.context?.path ?? "unknown";
102
+ return `파일 또는 디렉토리를 찾을 수 없습니다: ${path}`;
103
+ }
104
+ if (info.code === "EACCES" || info.code === "EPERM") {
105
+ return "파일 접근 권한을 확인해주세요.";
106
+ }
107
+ return "시스템 리소스를 확인해주세요.";
108
+
109
+ case "external":
110
+ return "외부 서비스에 문제가 있습니다. 잠시 후 다시 시도해주세요.";
111
+
112
+ case "internal":
113
+ return "내부 오류가 발생했습니다. 문제가 지속되면 이슈를 보고해주세요.";
114
+
115
+ default:
116
+ return undefined;
117
+ }
118
+ }
119
+
120
+ /**
121
+ * 도구별 특화된 에러 제안
122
+ */
123
+ function getToolSpecificSuggestion(toolName: string, info: ExtractedErrorInfo): string | undefined {
124
+ // spec 관련 도구
125
+ if (toolName.startsWith("mandu_") && toolName.includes("route")) {
126
+ if (info.code === "ENOENT") {
127
+ return "routes.manifest.json 파일이 없습니다. `mandu init`을 먼저 실행해주세요.";
128
+ }
129
+ if (info.message.includes("not found")) {
130
+ return "해당 라우트를 찾을 수 없습니다. `mandu_list_routes`로 존재하는 라우트를 확인해주세요.";
131
+ }
132
+ }
133
+
134
+ // guard 관련 도구
135
+ if (toolName === "mandu_guard_check") {
136
+ if (info.category === "config") {
137
+ return "Guard 설정을 확인해주세요. mandu.config.ts의 guard 섹션을 검토해주세요.";
138
+ }
139
+ }
140
+
141
+ // contract 관련 도구
142
+ if (toolName.includes("contract")) {
143
+ if (info.category === "validation") {
144
+ return "Contract 스키마가 올바른지 확인해주세요. Zod 스키마 문법을 확인해주세요.";
145
+ }
146
+ }
147
+
148
+ // generate 관련 도구
149
+ if (toolName === "mandu_generate") {
150
+ if (info.code === "EEXIST") {
151
+ return "파일이 이미 존재합니다. 덮어쓰려면 force 옵션을 사용해주세요.";
152
+ }
153
+ }
154
+
155
+ // transaction 관련 도구
156
+ if (toolName.includes("tx") || toolName.includes("transaction")) {
157
+ if (info.message.includes("no active")) {
158
+ return "활성화된 트랜잭션이 없습니다. `mandu_begin`으로 트랜잭션을 시작해주세요.";
159
+ }
160
+ }
161
+
162
+ return undefined;
163
+ }
164
+
165
+ /**
166
+ * 도구 실행 결과를 MCP 응답으로 변환
167
+ *
168
+ * @example
169
+ * ```ts
170
+ * // 성공 응답
171
+ * const response = createToolResponse("mandu_list_routes", { routes: [...] });
172
+ *
173
+ * // 에러 응답
174
+ * const response = createToolResponse("mandu_list_routes", null, new Error("..."));
175
+ * ```
176
+ */
177
+ export function createToolResponse(
178
+ toolName: string,
179
+ result: unknown,
180
+ error?: unknown
181
+ ): McpToolResponse {
182
+ if (error) {
183
+ const errorResponse = formatMcpError(error, toolName);
184
+ return {
185
+ content: [
186
+ {
187
+ type: "text",
188
+ text: JSON.stringify(errorResponse, null, 2),
189
+ },
190
+ ],
191
+ isError: true,
192
+ };
193
+ }
194
+
195
+ return {
196
+ content: [
197
+ {
198
+ type: "text",
199
+ text: JSON.stringify(result, null, 2),
200
+ },
201
+ ],
202
+ };
203
+ }
204
+
205
+ /**
206
+ * 에러 응답인지 확인
207
+ */
208
+ export function isErrorResponse(response: McpToolResponse): boolean {
209
+ return response.isError === true;
210
+ }
211
+
212
+ /**
213
+ * 에러 응답에서 McpErrorResponse 추출
214
+ */
215
+ export function extractErrorFromResponse(response: McpToolResponse): McpErrorResponse | null {
216
+ if (!response.isError) return null;
217
+
218
+ try {
219
+ const text = response.content[0]?.text;
220
+ if (!text) return null;
221
+ return JSON.parse(text) as McpErrorResponse;
222
+ } catch {
223
+ return null;
224
+ }
225
+ }
226
+
227
+ /**
228
+ * 에러 로깅 헬퍼
229
+ */
230
+ export function logToolError(
231
+ toolName: string,
232
+ error: unknown,
233
+ args?: Record<string, unknown>
234
+ ): void {
235
+ const info = extractErrorInfo(error);
236
+
237
+ console.error(`[MCP:${toolName}] ${info.category.toUpperCase()}: ${info.message}`);
238
+
239
+ if (info.code) {
240
+ console.error(` Code: ${info.code}`);
241
+ }
242
+
243
+ if (args && Object.keys(args).length > 0) {
244
+ console.error(` Args:`, JSON.stringify(args, null, 2));
245
+ }
246
+
247
+ if (info.context && Object.keys(info.context).length > 0) {
248
+ console.error(` Context:`, info.context);
249
+ }
250
+ }
@@ -1,22 +1,22 @@
1
- /**
2
- * MCP Executor
3
- *
4
- * 도구 실행 및 에러 처리
5
- */
6
-
7
- export {
8
- formatMcpError,
9
- createToolResponse,
10
- isErrorResponse,
11
- extractErrorFromResponse,
12
- logToolError,
13
- type McpErrorResponse,
14
- type McpToolResponse,
15
- } from "./error-handler.js";
16
-
17
- export {
18
- ToolExecutor,
19
- createToolExecutor,
20
- type ToolExecutorOptions,
21
- type ExecutionResult,
22
- } from "./tool-executor.js";
1
+ /**
2
+ * MCP Executor
3
+ *
4
+ * 도구 실행 및 에러 처리
5
+ */
6
+
7
+ export {
8
+ formatMcpError,
9
+ createToolResponse,
10
+ isErrorResponse,
11
+ extractErrorFromResponse,
12
+ logToolError,
13
+ type McpErrorResponse,
14
+ type McpToolResponse,
15
+ } from "./error-handler.js";
16
+
17
+ export {
18
+ ToolExecutor,
19
+ createToolExecutor,
20
+ type ToolExecutorOptions,
21
+ type ExecutionResult,
22
+ } from "./tool-executor.js";