@mandujs/mcp 0.9.18 → 0.9.20

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mandujs/mcp",
3
- "version": "0.9.18",
3
+ "version": "0.9.20",
4
4
  "description": "Mandu MCP Server - Agent-native interface for Mandu framework operations",
5
5
  "type": "module",
6
6
  "main": "./src/index.ts",
@@ -378,19 +378,19 @@ function generateClientSlotTemplate(routeId: string, slotModule?: string): strin
378
378
  .map((s) => s.charAt(0).toUpperCase() + s.slice(1))
379
379
  .join("");
380
380
 
381
- const typeImport = slotModule
382
- ? `// Import types from server slot if needed
383
- // import type { LoaderData } from "./${routeId}.slot";
384
-
385
- `
386
- : "";
381
+ const typeImport = slotModule
382
+ ? `// Import types from server slot if needed (adjust path to your project)
383
+ // import type { LoaderData } from "../../../spec/slots/${routeId}.slot";
384
+
385
+ `
386
+ : "";
387
387
 
388
388
  return `/**
389
389
  * ${pascalCase} Client Slot
390
390
  * 브라우저에서 실행되는 클라이언트 로직
391
391
  */
392
392
 
393
- import { Mandu } from "@mandujs/core/client";
393
+ import { ManduClient } from "@mandujs/core/client";
394
394
  import { useState, useCallback } from "react";
395
395
 
396
396
  ${typeImport}// 서버에서 전달받는 데이터 타입
@@ -399,7 +399,7 @@ interface ServerData {
399
399
  [key: string]: unknown;
400
400
  }
401
401
 
402
- export default Mandu.island<ServerData>({
402
+ export default ManduClient.island<ServerData>({
403
403
  /**
404
404
  * Setup Phase
405
405
  * - 서버 데이터를 받아 클라이언트 상태 초기화
package/src/tools/slot.ts CHANGED
@@ -3,12 +3,10 @@ import {
3
3
  loadManifest,
4
4
  validateSlotContent,
5
5
  correctSlotContent,
6
- runSlotCorrection,
7
6
  summarizeValidationIssues,
8
7
  } from "@mandujs/core";
9
8
  import { getProjectPaths, isInsideProject } from "../utils/project.js";
10
9
  import path from "path";
11
- import fs from "fs/promises";
12
10
 
13
11
  export const slotToolDefinitions: Tool[] = [
14
12
  {
@@ -25,40 +23,6 @@ export const slotToolDefinitions: Tool[] = [
25
23
  required: ["routeId"],
26
24
  },
27
25
  },
28
- {
29
- name: "mandu_write_slot",
30
- description:
31
- "Write or update the contents of a slot file with optional auto-correction",
32
- inputSchema: {
33
- type: "object",
34
- properties: {
35
- routeId: {
36
- type: "string",
37
- description: "The route ID whose slot file to write",
38
- },
39
- content: {
40
- type: "string",
41
- description: "The TypeScript content to write to the slot file",
42
- },
43
- autoCorrect: {
44
- type: "boolean",
45
- description:
46
- "If true, automatically fix correctable issues (default: false)",
47
- },
48
- maxRetries: {
49
- type: "number",
50
- description:
51
- "Maximum correction attempts when autoCorrect is true (default: 3)",
52
- },
53
- validateOnly: {
54
- type: "boolean",
55
- description:
56
- "If true, only validate without writing (default: false)",
57
- },
58
- },
59
- required: ["routeId", "content"],
60
- },
61
- },
62
26
  {
63
27
  name: "mandu_validate_slot",
64
28
  description:
@@ -141,166 +105,6 @@ export function slotTools(projectRoot: string) {
141
105
  }
142
106
  },
143
107
 
144
- mandu_write_slot: async (args: Record<string, unknown>) => {
145
- const {
146
- routeId,
147
- content,
148
- autoCorrect = false,
149
- maxRetries = 3,
150
- validateOnly = false,
151
- } = args as {
152
- routeId: string;
153
- content: string;
154
- autoCorrect?: boolean;
155
- maxRetries?: number;
156
- validateOnly?: boolean;
157
- };
158
-
159
- // Load manifest to find the route
160
- const manifestResult = await loadManifest(paths.manifestPath);
161
- if (!manifestResult.success || !manifestResult.data) {
162
- return { error: manifestResult.errors };
163
- }
164
-
165
- const route = manifestResult.data.routes.find((r) => r.id === routeId);
166
- if (!route) {
167
- return { error: `Route not found: ${routeId}` };
168
- }
169
-
170
- if (!route.slotModule) {
171
- return {
172
- error: `Route '${routeId}' does not have a slotModule defined`,
173
- tip: "Add slotModule to the route spec first",
174
- };
175
- }
176
-
177
- const slotPath = path.join(projectRoot, route.slotModule);
178
-
179
- // Security check
180
- if (!isInsideProject(slotPath, projectRoot)) {
181
- return { error: "Slot path is outside project directory" };
182
- }
183
-
184
- // 1. 초기 검증
185
- const initialValidation = validateSlotContent(content);
186
-
187
- // validateOnly 모드면 검증 결과만 반환
188
- if (validateOnly) {
189
- return {
190
- validateOnly: true,
191
- valid: initialValidation.valid,
192
- summary: summarizeValidationIssues(initialValidation.issues),
193
- issues: initialValidation.issues,
194
- tip: initialValidation.valid
195
- ? "Content is valid and ready to write"
196
- : "Fix the issues and try again, or use autoCorrect: true",
197
- };
198
- }
199
-
200
- // 2. autoCorrect 모드
201
- let finalContent = content;
202
- let correctionResult = null;
203
-
204
- if (autoCorrect && !initialValidation.valid) {
205
- correctionResult = await runSlotCorrection(
206
- content,
207
- validateSlotContent,
208
- maxRetries
209
- );
210
- finalContent = correctionResult.finalContent;
211
-
212
- // 여전히 에러가 있으면 쓰기 거부
213
- if (!correctionResult.success) {
214
- const errors = correctionResult.remainingIssues.filter(
215
- (i) => i.severity === "error"
216
- );
217
- if (errors.length > 0) {
218
- return {
219
- success: false,
220
- autoCorrectAttempted: true,
221
- attempts: correctionResult.attempts,
222
- appliedFixes: correctionResult.allFixes,
223
- remainingErrors: errors,
224
- summary: `${correctionResult.allFixes.length}개 문제 수정, ${errors.length}개 에러 남음`,
225
- tip: "수동으로 수정이 필요한 에러가 있습니다",
226
- suggestedContent: finalContent, // 부분적으로 수정된 내용 제공
227
- };
228
- }
229
- }
230
- } else if (!autoCorrect && !initialValidation.valid) {
231
- // autoCorrect 없이 에러가 있으면 경고와 함께 진행 여부 결정
232
- const errors = initialValidation.issues.filter(
233
- (i) => i.severity === "error"
234
- );
235
- if (errors.length > 0) {
236
- return {
237
- success: false,
238
- valid: false,
239
- errors,
240
- summary: summarizeValidationIssues(initialValidation.issues),
241
- tip: "Use autoCorrect: true to attempt automatic fixes, or fix manually",
242
- autoFixable: initialValidation.issues
243
- .filter((i) => i.autoFixable)
244
- .map((i) => i.code),
245
- };
246
- }
247
- }
248
-
249
- // 3. 파일 쓰기
250
- try {
251
- // Ensure directory exists
252
- const slotDir = path.dirname(slotPath);
253
- await fs.mkdir(slotDir, { recursive: true });
254
-
255
- // Check if file exists (for backup/warning)
256
- const file = Bun.file(slotPath);
257
- const existed = await file.exists();
258
- let previousContent: string | null = null;
259
-
260
- if (existed) {
261
- previousContent = await file.text();
262
- }
263
-
264
- // Write the new content
265
- await Bun.write(slotPath, finalContent);
266
-
267
- // 최종 검증
268
- const finalValidation = validateSlotContent(finalContent);
269
-
270
- const result: Record<string, unknown> = {
271
- success: true,
272
- slotPath: route.slotModule,
273
- action: existed ? "updated" : "created",
274
- lineCount: finalContent.split("\n").length,
275
- previousLineCount: previousContent
276
- ? previousContent.split("\n").length
277
- : null,
278
- validation: {
279
- valid: finalValidation.valid,
280
- summary: summarizeValidationIssues(finalValidation.issues),
281
- warnings: finalValidation.issues.filter(
282
- (i) => i.severity === "warning"
283
- ),
284
- },
285
- };
286
-
287
- // autoCorrect 결과 추가
288
- if (correctionResult) {
289
- result.autoCorrection = {
290
- applied: true,
291
- attempts: correctionResult.attempts,
292
- fixes: correctionResult.allFixes,
293
- };
294
- }
295
-
296
- return result;
297
- } catch (error) {
298
- return {
299
- error: `Failed to write slot file: ${error instanceof Error ? error.message : String(error)}`,
300
- };
301
- }
302
- },
303
-
304
108
  mandu_validate_slot: async (args: Record<string, unknown>) => {
305
109
  const { content } = args as { content: string };
306
110
 
@@ -342,10 +146,10 @@ export function slotTools(projectRoot: string) {
342
146
  })),
343
147
  correctionPreview,
344
148
  tip: validation.valid
345
- ? "Content is valid"
149
+ ? "Content is valid. Use Edit tool to write the slot file."
346
150
  : autoFixable.length > 0
347
- ? "Use mandu_write_slot with autoCorrect: true to auto-fix"
348
- : "Manual fixes required before writing",
151
+ ? "Auto-fixable issues found. Apply corrections and use Edit tool to write."
152
+ : "Manual fixes required before writing. Use Edit tool after fixing.",
349
153
  };
350
154
  },
351
155
  };