@mandujs/mcp 0.13.0 → 0.17.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 (136) hide show
  1. package/README.md +102 -7
  2. package/package.json +3 -2
  3. package/src/adapters/index.ts +20 -20
  4. package/src/adapters/monitor-adapter.ts +100 -100
  5. package/src/adapters/tool-adapter.ts +88 -88
  6. package/src/executor/error-handler.ts +250 -250
  7. package/src/executor/index.ts +22 -22
  8. package/src/executor/tool-executor.ts +148 -148
  9. package/src/hooks/config-watcher.ts +174 -174
  10. package/src/hooks/index.ts +23 -23
  11. package/src/hooks/mcp-hooks.ts +227 -227
  12. package/src/logging/index.ts +15 -15
  13. package/src/logging/mcp-transport.ts +134 -134
  14. package/src/registry/index.ts +13 -13
  15. package/src/registry/mcp-tool-registry.ts +298 -298
  16. package/src/resources/skills/guides.ts +1136 -1136
  17. package/src/resources/skills/index.ts +12 -12
  18. package/src/resources/skills/loader.ts +218 -218
  19. package/src/resources/skills/mandu-composition/SKILL.md +91 -91
  20. package/src/resources/skills/mandu-composition/metadata.json +13 -13
  21. package/src/resources/skills/mandu-composition/rules/_sections.md +26 -26
  22. package/src/resources/skills/mandu-composition/rules/_template.md +77 -77
  23. package/src/resources/skills/mandu-composition/rules/comp-arch-avoid-boolean-props.md +146 -146
  24. package/src/resources/skills/mandu-composition/rules/comp-arch-compound-components.md +164 -164
  25. package/src/resources/skills/mandu-composition/rules/comp-island-event.md +161 -161
  26. package/src/resources/skills/mandu-composition/rules/comp-island-slot-split.md +167 -167
  27. package/src/resources/skills/mandu-composition/rules/comp-pattern-children.md +149 -149
  28. package/src/resources/skills/mandu-composition/rules/comp-state-context-interface.md +148 -148
  29. package/src/resources/skills/mandu-composition/rules/comp-state-lift-state.md +150 -150
  30. package/src/resources/skills/mandu-deployment/SKILL.md +92 -92
  31. package/src/resources/skills/mandu-deployment/_sections.md +41 -41
  32. package/src/resources/skills/mandu-deployment/_template.md +38 -38
  33. package/src/resources/skills/mandu-deployment/metadata.json +13 -13
  34. package/src/resources/skills/mandu-deployment/rules/deploy-build-bun.md +109 -109
  35. package/src/resources/skills/mandu-deployment/rules/deploy-build-output.md +115 -115
  36. package/src/resources/skills/mandu-deployment/rules/deploy-cicd-github.md +219 -219
  37. package/src/resources/skills/mandu-deployment/rules/deploy-docker-bun.md +150 -150
  38. package/src/resources/skills/mandu-deployment/rules/deploy-docker-compose.md +223 -223
  39. package/src/resources/skills/mandu-deployment/rules/deploy-platform-fly.md +152 -152
  40. package/src/resources/skills/mandu-deployment/rules/deploy-platform-render.md +179 -179
  41. package/src/resources/skills/mandu-deployment/rules/deploy-platform-supabase.md +323 -323
  42. package/src/resources/skills/mandu-deployment/rules/deploy-platform-vercel.md +140 -140
  43. package/src/resources/skills/mandu-fs-routes/SKILL.md +82 -82
  44. package/src/resources/skills/mandu-fs-routes/metadata.json +12 -12
  45. package/src/resources/skills/mandu-fs-routes/rules/_sections.md +36 -36
  46. package/src/resources/skills/mandu-fs-routes/rules/_template.md +69 -69
  47. package/src/resources/skills/mandu-fs-routes/rules/routes-api-methods.md +65 -65
  48. package/src/resources/skills/mandu-fs-routes/rules/routes-dynamic-param.md +93 -93
  49. package/src/resources/skills/mandu-fs-routes/rules/routes-naming-page.md +55 -55
  50. package/src/resources/skills/mandu-guard/SKILL.md +129 -129
  51. package/src/resources/skills/mandu-guard/metadata.json +12 -12
  52. package/src/resources/skills/mandu-guard/rules/_sections.md +36 -36
  53. package/src/resources/skills/mandu-guard/rules/_template.md +82 -82
  54. package/src/resources/skills/mandu-guard/rules/guard-config-rules.md +100 -100
  55. package/src/resources/skills/mandu-guard/rules/guard-layer-direction.md +76 -76
  56. package/src/resources/skills/mandu-guard/rules/guard-preset-mandu.md +81 -81
  57. package/src/resources/skills/mandu-guard/rules/guard-validate-import.md +80 -80
  58. package/src/resources/skills/mandu-hydration/SKILL.md +91 -91
  59. package/src/resources/skills/mandu-hydration/metadata.json +12 -12
  60. package/src/resources/skills/mandu-hydration/rules/_sections.md +31 -31
  61. package/src/resources/skills/mandu-hydration/rules/_template.md +72 -72
  62. package/src/resources/skills/mandu-hydration/rules/hydration-data-event.md +109 -109
  63. package/src/resources/skills/mandu-hydration/rules/hydration-directive-use-client.md +55 -55
  64. package/src/resources/skills/mandu-hydration/rules/hydration-island-setup.md +113 -113
  65. package/src/resources/skills/mandu-hydration/rules/hydration-priority-visible.md +68 -68
  66. package/src/resources/skills/mandu-performance/SKILL.md +85 -85
  67. package/src/resources/skills/mandu-performance/metadata.json +14 -14
  68. package/src/resources/skills/mandu-performance/rules/_sections.md +31 -31
  69. package/src/resources/skills/mandu-performance/rules/_template.md +64 -64
  70. package/src/resources/skills/mandu-performance/rules/perf-async-defer-await.md +103 -103
  71. package/src/resources/skills/mandu-performance/rules/perf-async-parallel.md +95 -95
  72. package/src/resources/skills/mandu-performance/rules/perf-bun-file.md +124 -124
  73. package/src/resources/skills/mandu-performance/rules/perf-bun-serve.md +125 -125
  74. package/src/resources/skills/mandu-performance/rules/perf-bundle-imports.md +80 -80
  75. package/src/resources/skills/mandu-performance/rules/perf-bundle-island-lazy.md +145 -145
  76. package/src/resources/skills/mandu-performance/rules/perf-cache-react.md +98 -98
  77. package/src/resources/skills/mandu-performance/rules/perf-render-transitions.md +154 -154
  78. package/src/resources/skills/mandu-security/SKILL.md +87 -87
  79. package/src/resources/skills/mandu-security/metadata.json +13 -13
  80. package/src/resources/skills/mandu-security/rules/_sections.md +31 -31
  81. package/src/resources/skills/mandu-security/rules/_template.md +74 -74
  82. package/src/resources/skills/mandu-security/rules/sec-auth-guard.md +127 -127
  83. package/src/resources/skills/mandu-security/rules/sec-env-management.md +133 -133
  84. package/src/resources/skills/mandu-security/rules/sec-input-validate.md +148 -148
  85. package/src/resources/skills/mandu-security/rules/sec-protect-csrf.md +146 -146
  86. package/src/resources/skills/mandu-security/rules/sec-protect-headers.md +138 -138
  87. package/src/resources/skills/mandu-slot/SKILL.md +85 -85
  88. package/src/resources/skills/mandu-slot/metadata.json +12 -12
  89. package/src/resources/skills/mandu-slot/rules/_sections.md +36 -36
  90. package/src/resources/skills/mandu-slot/rules/_template.md +63 -63
  91. package/src/resources/skills/mandu-slot/rules/slot-basic-structure.md +38 -38
  92. package/src/resources/skills/mandu-slot/rules/slot-ctx-response.md +56 -56
  93. package/src/resources/skills/mandu-slot/rules/slot-guard-auth.md +59 -59
  94. package/src/resources/skills/mandu-slot/rules/slot-http-methods.md +64 -64
  95. package/src/resources/skills/mandu-styling/SKILL.md +154 -154
  96. package/src/resources/skills/mandu-styling/_sections.md +43 -43
  97. package/src/resources/skills/mandu-styling/_template.md +32 -32
  98. package/src/resources/skills/mandu-styling/metadata.json +15 -15
  99. package/src/resources/skills/mandu-styling/rules/style-component-compound.md +235 -235
  100. package/src/resources/skills/mandu-styling/rules/style-component-slots.md +255 -255
  101. package/src/resources/skills/mandu-styling/rules/style-component-tokens.md +205 -205
  102. package/src/resources/skills/mandu-styling/rules/style-island-animations.md +272 -272
  103. package/src/resources/skills/mandu-styling/rules/style-island-scoping.md +167 -167
  104. package/src/resources/skills/mandu-styling/rules/style-island-variants.md +221 -221
  105. package/src/resources/skills/mandu-styling/rules/style-perf-critical.md +209 -209
  106. package/src/resources/skills/mandu-styling/rules/style-perf-purge.md +192 -192
  107. package/src/resources/skills/mandu-styling/rules/style-setup-modules.md +162 -162
  108. package/src/resources/skills/mandu-styling/rules/style-setup-panda.md +164 -164
  109. package/src/resources/skills/mandu-styling/rules/style-setup-tailwind.md +170 -170
  110. package/src/resources/skills/mandu-styling/rules/style-tailwind-v4-gotchas.md +179 -179
  111. package/src/resources/skills/mandu-styling/rules/style-theme-darkmode.md +229 -229
  112. package/src/resources/skills/mandu-testing/SKILL.md +99 -99
  113. package/src/resources/skills/mandu-testing/metadata.json +13 -13
  114. package/src/resources/skills/mandu-testing/rules/_sections.md +26 -26
  115. package/src/resources/skills/mandu-testing/rules/_template.md +65 -65
  116. package/src/resources/skills/mandu-testing/rules/test-component-island.md +195 -195
  117. package/src/resources/skills/mandu-testing/rules/test-e2e-playwright.md +196 -196
  118. package/src/resources/skills/mandu-testing/rules/test-mock-fetch.md +219 -219
  119. package/src/resources/skills/mandu-testing/rules/test-slot-unit.md +192 -192
  120. package/src/resources/skills/mandu-ui/SKILL.md +117 -117
  121. package/src/resources/skills/mandu-ui/_sections.md +23 -23
  122. package/src/resources/skills/mandu-ui/_template.md +32 -32
  123. package/src/resources/skills/mandu-ui/metadata.json +13 -13
  124. package/src/resources/skills/mandu-ui/rules/ui-accessibility-aria.md +232 -232
  125. package/src/resources/skills/mandu-ui/rules/ui-accessibility-focus.md +238 -238
  126. package/src/resources/skills/mandu-ui/rules/ui-composition-patterns.md +259 -259
  127. package/src/resources/skills/mandu-ui/rules/ui-island-integration.md +258 -258
  128. package/src/resources/skills/mandu-ui/rules/ui-radix-patterns.md +213 -213
  129. package/src/resources/skills/mandu-ui/rules/ui-shadcn-setup.md +209 -209
  130. package/src/resources/skills/recipes.ts +932 -932
  131. package/src/tools/ate.ts +219 -0
  132. package/src/tools/index.ts +4 -1
  133. package/src/tools/project.ts +334 -334
  134. package/src/tools/runtime.ts +497 -497
  135. package/src/tools/seo.ts +417 -417
  136. 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";