@mandujs/mcp 0.18.2 → 0.18.4

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.18.2",
3
+ "version": "0.18.4",
4
4
  "description": "Mandu MCP Server - Agent-native interface for Mandu framework operations",
5
5
  "type": "module",
6
6
  "main": "./src/index.ts",
@@ -7,7 +7,7 @@
7
7
 
8
8
  import fs from "fs";
9
9
  import path from "path";
10
- import { spawn, type ChildProcess } from "child_process";
10
+ import type { Subprocess } from "bun";
11
11
 
12
12
  const TOOL_ICONS: Record<string, string> = {
13
13
  // Spec
@@ -266,7 +266,7 @@ function writeDefaultConfig(projectRoot: string, config: Required<MonitorConfig>
266
266
  export class ActivityMonitor {
267
267
  private logFile = "";
268
268
  private logStream: fs.WriteStream | null = null;
269
- private tailProcess: ChildProcess | null = null;
269
+ private tailProcess: Subprocess | null = null;
270
270
  private projectRoot: string;
271
271
  private config: Required<MonitorConfig>;
272
272
  private outputFormat: MonitorOutputFormat;
@@ -813,9 +813,9 @@ export class ActivityMonitor {
813
813
  private openTerminal(): void {
814
814
  try {
815
815
  if (process.platform === "win32") {
816
- this.tailProcess = spawn(
817
- "cmd",
816
+ this.tailProcess = Bun.spawn(
818
817
  [
818
+ "cmd",
819
819
  "/c",
820
820
  "start",
821
821
  "Mandu Activity Monitor",
@@ -824,22 +824,19 @@ export class ActivityMonitor {
824
824
  "-Command",
825
825
  `[Console]::OutputEncoding = [System.Text.Encoding]::UTF8; chcp 65001 | Out-Null; Get-Content '${this.logFile}' -Wait -Encoding UTF8`,
826
826
  ],
827
- { cwd: this.projectRoot, detached: true, stdio: "ignore" }
827
+ { cwd: this.projectRoot, stdio: ["ignore", "ignore", "ignore"] }
828
828
  );
829
829
  } else if (process.platform === "darwin") {
830
- this.tailProcess = spawn(
831
- "osascript",
832
- ["-e", `tell application "Terminal" to do script "tail -f '${this.logFile}'"`],
833
- { detached: true, stdio: "ignore" }
830
+ this.tailProcess = Bun.spawn(
831
+ ["osascript", "-e", `tell application "Terminal" to do script "tail -f '${this.logFile}'"`],
832
+ { stdio: ["ignore", "ignore", "ignore"] }
834
833
  );
835
834
  } else {
836
- this.tailProcess = spawn(
837
- "x-terminal-emulator",
838
- ["-e", `tail -f '${this.logFile}'`],
839
- { cwd: this.projectRoot, detached: true, stdio: "ignore" }
835
+ this.tailProcess = Bun.spawn(
836
+ ["x-terminal-emulator", "-e", `tail -f '${this.logFile}'`],
837
+ { cwd: this.projectRoot, stdio: ["ignore", "ignore", "ignore"] }
840
838
  );
841
839
  }
842
- this.tailProcess?.unref();
843
840
  } catch {
844
841
  // Terminal auto-open failed silently
845
842
  }
package/src/server.ts CHANGED
@@ -322,7 +322,10 @@ export class ManduMcpServer {
322
322
  * 리소스 패턴 매칭
323
323
  */
324
324
  function matchResourcePattern(pattern: string, uri: string): boolean {
325
- const regexPattern = pattern.replace(/\{[^}]+\}/g, "([^/]+)");
325
+ const regexPattern = pattern
326
+ .split(/\{[^}]+\}/)
327
+ .map(part => part.replace(/[.+*?^${}()|[\]\\]/g, "\\$&"))
328
+ .join("([^/]+)");
326
329
  const regex = new RegExp(`^${regexPattern}$`);
327
330
  return regex.test(uri);
328
331
  }
@@ -332,10 +335,16 @@ function matchResourcePattern(pattern: string, uri: string): boolean {
332
335
  */
333
336
  function extractResourceParams(pattern: string, uri: string): Record<string, string> {
334
337
  const paramNames: string[] = [];
335
- const regexPattern = pattern.replace(/\{([^}]+)\}/g, (_, name) => {
336
- paramNames.push(name);
337
- return "([^/]+)";
338
- });
338
+ const regexPattern = pattern
339
+ .split(/\{([^}]+)\}/)
340
+ .map((part, index) => {
341
+ if (index % 2 === 1) {
342
+ paramNames.push(part);
343
+ return "([^/]+)";
344
+ }
345
+ return part.replace(/[.+*?^${}()|[\]\\]/g, "\\$&");
346
+ })
347
+ .join("");
339
348
 
340
349
  const regex = new RegExp(`^${regexPattern}$`);
341
350
  const match = uri.match(regex);
package/src/tools/ate.ts CHANGED
@@ -14,61 +14,110 @@ import {
14
14
  export const ateToolDefinitions: Tool[] = [
15
15
  {
16
16
  name: "mandu.ate.extract",
17
- description: "ATE: AST 기반 상호작용 그래프 추출",
17
+ description:
18
+ "ATE Step 1 — Extract: Statically analyze the Mandu project's AST to build an interaction graph of routes, slots, contracts, and data flow. " +
19
+ "Identifies all testable interactions without running the server. " +
20
+ "Output is stored in .mandu/ate/extract/ and used by mandu.ate.generate.",
18
21
  inputSchema: {
19
22
  type: "object",
20
23
  properties: {
21
- repoRoot: { type: "string" },
22
- tsconfigPath: { type: "string" },
23
- routeGlobs: { type: "array", items: { type: "string" } },
24
- buildSalt: { type: "string" },
24
+ repoRoot: { type: "string", description: "Absolute path to the Mandu project root" },
25
+ tsconfigPath: { type: "string", description: "Path to tsconfig.json (default: tsconfig.json in repoRoot)" },
26
+ routeGlobs: {
27
+ type: "array",
28
+ items: { type: "string" },
29
+ description: "Glob patterns to limit which routes are analyzed (e.g. ['app/api/**', 'app/blog/**']). Omit for all routes.",
30
+ },
31
+ buildSalt: {
32
+ type: "string",
33
+ description: "Cache invalidation salt — change this to force re-extraction even if source hasn't changed",
34
+ },
25
35
  },
26
36
  required: ["repoRoot"],
27
37
  },
28
38
  },
29
39
  {
30
40
  name: "mandu.ate.generate",
31
- description: "ATE: 시나리오 생성 + Playwright spec codegen",
41
+ description:
42
+ "ATE Step 2 — Generate: Create Playwright test scenarios from the interaction graph produced by mandu.ate.extract. " +
43
+ "Oracle level controls assertion depth: " +
44
+ "L0 = no assertions (smoke test only), " +
45
+ "L1 = basic HTTP status checks, " +
46
+ "L2 = contract schema validation (response shape matches Zod contract), " +
47
+ "L3 = full behavioral contract (side effects, state changes, error paths). " +
48
+ "Output: .mandu/ate/tests/*.spec.ts ready to run with Playwright.",
32
49
  inputSchema: {
33
50
  type: "object",
34
51
  properties: {
35
- repoRoot: { type: "string" },
36
- oracleLevel: { type: "string", enum: ["L0", "L1", "L2", "L3"] },
37
- onlyRoutes: { type: "array", items: { type: "string" } },
52
+ repoRoot: { type: "string", description: "Absolute path to the Mandu project root" },
53
+ oracleLevel: {
54
+ type: "string",
55
+ enum: ["L0", "L1", "L2", "L3"],
56
+ description: "Assertion depth: L0=smoke, L1=HTTP status, L2=contract schema, L3=full behavioral",
57
+ },
58
+ onlyRoutes: {
59
+ type: "array",
60
+ items: { type: "string" },
61
+ description: "Limit test generation to specific routeIds (e.g. ['api-users', 'blog-slug']). Omit for all routes.",
62
+ },
38
63
  },
39
64
  required: ["repoRoot"],
40
65
  },
41
66
  },
42
67
  {
43
68
  name: "mandu.ate.run",
44
- description: "ATE: Playwright runner 실행(artifacts 수집)",
69
+ description:
70
+ "ATE Step 3 — Run: Execute the generated Playwright specs against a running Mandu dev server. " +
71
+ "Collects test artifacts (screenshots, traces, results) in .mandu/ate/runs/{runId}/. " +
72
+ "Requires the Mandu dev server to be running (use mandu_dev_start first). " +
73
+ "Returns a runId for use with mandu.ate.report and mandu.ate.heal.",
45
74
  inputSchema: {
46
75
  type: "object",
47
76
  properties: {
48
- repoRoot: { type: "string" },
49
- baseURL: { type: "string" },
50
- ci: { type: "boolean" },
51
- headless: { type: "boolean" },
52
- browsers: { type: "array", items: { type: "string", enum: ["chromium", "firefox", "webkit"] } },
77
+ repoRoot: { type: "string", description: "Absolute path to the Mandu project root" },
78
+ baseURL: {
79
+ type: "string",
80
+ description: "Dev server URL (default: http://localhost:3333). Must match the running mandu dev server.",
81
+ },
82
+ ci: { type: "boolean", description: "CI mode: stricter timeouts, no interactive prompts" },
83
+ headless: { type: "boolean", description: "Run browsers headlessly (default: true)" },
84
+ browsers: {
85
+ type: "array",
86
+ items: { type: "string", enum: ["chromium", "firefox", "webkit"] },
87
+ description: "Browsers to test against (default: ['chromium'])",
88
+ },
53
89
  },
54
90
  required: ["repoRoot"],
55
91
  },
56
92
  },
57
93
  {
58
94
  name: "mandu.ate.report",
59
- description: "ATE: 테스트 리포트 생성 (JSON, HTML, 또는 both)",
95
+ description:
96
+ "ATE Step 4 — Report: Generate a test report from run artifacts. " +
97
+ "Produces pass/fail summary, coverage by route, and failure details. " +
98
+ "Use the runId returned by mandu.ate.run. " +
99
+ "If tests failed, follow up with mandu.ate.heal to get fix suggestions.",
60
100
  inputSchema: {
61
101
  type: "object",
62
102
  properties: {
63
- repoRoot: { type: "string" },
64
- runId: { type: "string" },
65
- startedAt: { type: "string" },
66
- finishedAt: { type: "string" },
67
- exitCode: { type: "number" },
68
- oracleLevel: { type: "string", enum: ["L0", "L1", "L2", "L3"] },
69
- format: { type: "string", enum: ["json", "html", "both"], description: "리포트 포맷 (기본값: both)" },
103
+ repoRoot: { type: "string", description: "Absolute path to the Mandu project root" },
104
+ runId: { type: "string", description: "Run ID returned by mandu.ate.run" },
105
+ startedAt: { type: "string", description: "ISO timestamp when run started" },
106
+ finishedAt: { type: "string", description: "ISO timestamp when run finished" },
107
+ exitCode: { type: "number", description: "Playwright process exit code (0=pass, non-zero=fail)" },
108
+ oracleLevel: {
109
+ type: "string",
110
+ enum: ["L0", "L1", "L2", "L3"],
111
+ description: "Oracle level used during generation (for report context)",
112
+ },
113
+ format: {
114
+ type: "string",
115
+ enum: ["json", "html", "both"],
116
+ description: "Report format: json (machine-readable), html (visual), both (default)",
117
+ },
70
118
  impact: {
71
119
  type: "object",
120
+ description: "Impact analysis context — set if tests were run on a subset of routes via mandu.ate.impact",
72
121
  properties: {
73
122
  mode: { type: "string", enum: ["full", "subset"] },
74
123
  changedFiles: { type: "array", items: { type: "string" } },
@@ -82,61 +131,89 @@ export const ateToolDefinitions: Tool[] = [
82
131
  },
83
132
  {
84
133
  name: "mandu.ate.heal",
85
- description: "ATE: 실패 원인 분류 + 복구 제안(diff) 생성 (자동 커밋 금지)",
134
+ description:
135
+ "ATE Step 5 — Heal: Analyze test failures from a run and generate safe diff suggestions for fixing the code. " +
136
+ "Classifies failures by root cause (schema mismatch, missing handler, wrong status, selector stale, etc.) " +
137
+ "and produces reviewable diffs — never auto-commits or overwrites files. " +
138
+ "Use mandu.ate.apply_heal to apply a specific suggestion after review. " +
139
+ "Supports rollback via mandu_rollback if applied changes cause regressions.",
86
140
  inputSchema: {
87
141
  type: "object",
88
142
  properties: {
89
- repoRoot: { type: "string" },
90
- runId: { type: "string" },
143
+ repoRoot: { type: "string", description: "Absolute path to the Mandu project root" },
144
+ runId: { type: "string", description: "Run ID from mandu.ate.run with failures to analyze" },
91
145
  },
92
146
  required: ["repoRoot", "runId"],
93
147
  },
94
148
  },
95
149
  {
96
150
  name: "mandu.ate.impact",
97
- description: "ATE: git diff 기반 subset 계산",
151
+ description:
152
+ "ATE Optimization — Impact Analysis: Calculate the minimal subset of routes affected by changed files using git diff. " +
153
+ "Avoids running the full test suite when only part of the codebase changed. " +
154
+ "Returns selectedRoutes to pass to mandu.ate.generate (onlyRoutes) or mandu.ate.run. " +
155
+ "Typical use: run after `git commit` to test only affected routes in CI.",
98
156
  inputSchema: {
99
157
  type: "object",
100
158
  properties: {
101
- repoRoot: { type: "string" },
102
- base: { type: "string" },
103
- head: { type: "string" },
159
+ repoRoot: { type: "string", description: "Absolute path to the Mandu project root" },
160
+ base: { type: "string", description: "Git base ref for diff (default: HEAD~1 or main branch)" },
161
+ head: { type: "string", description: "Git head ref for diff (default: current working tree)" },
104
162
  },
105
163
  required: ["repoRoot"],
106
164
  },
107
165
  },
108
166
  {
109
167
  name: "mandu.ate.auto_pipeline",
110
- description: "ATE: 전체 파이프라인 자동 실행 (Extract → Generate → Run → Report → Heal)",
168
+ description:
169
+ "ATE Full Pipeline — Run the complete ATE cycle in one call: " +
170
+ "Extract AST → Generate Playwright specs → Run tests → Create report → Suggest heals. " +
171
+ "Recommended for: initial setup, scheduled CI runs, and full regression testing. " +
172
+ "For incremental development, prefer individual steps (extract → generate → run → report → heal). " +
173
+ "Set useImpactAnalysis=true to automatically limit tests to changed routes.",
111
174
  inputSchema: {
112
175
  type: "object",
113
176
  properties: {
114
- repoRoot: { type: "string" },
115
- baseURL: { type: "string" },
116
- oracleLevel: { type: "string", enum: ["L0", "L1", "L2", "L3"] },
117
- ci: { type: "boolean" },
118
- useImpactAnalysis: { type: "boolean" },
119
- base: { type: "string" },
120
- head: { type: "string" },
121
- autoHeal: { type: "boolean" },
122
- tsconfigPath: { type: "string" },
123
- routeGlobs: { type: "array", items: { type: "string" } },
124
- buildSalt: { type: "string" },
177
+ repoRoot: { type: "string", description: "Absolute path to the Mandu project root" },
178
+ baseURL: { type: "string", description: "Dev server URL (default: http://localhost:3333)" },
179
+ oracleLevel: {
180
+ type: "string",
181
+ enum: ["L0", "L1", "L2", "L3"],
182
+ description: "Assertion depth: L0=smoke, L1=HTTP status, L2=contract schema, L3=full behavioral",
183
+ },
184
+ ci: { type: "boolean", description: "CI mode: stricter timeouts" },
185
+ useImpactAnalysis: {
186
+ type: "boolean",
187
+ description: "Run impact analysis first and only test changed routes (faster in CI)",
188
+ },
189
+ base: { type: "string", description: "Git base ref for impact analysis" },
190
+ head: { type: "string", description: "Git head ref for impact analysis" },
191
+ autoHeal: {
192
+ type: "boolean",
193
+ description: "Automatically run heal analysis after failures (produces diff suggestions, never auto-applies)",
194
+ },
195
+ tsconfigPath: { type: "string", description: "Path to tsconfig.json" },
196
+ routeGlobs: { type: "array", items: { type: "string" }, description: "Limit extraction to specific route patterns" },
197
+ buildSalt: { type: "string", description: "Cache invalidation salt for extraction" },
125
198
  },
126
199
  required: ["repoRoot"],
127
200
  },
128
201
  },
129
202
  {
130
203
  name: "mandu.ate.feedback",
131
- description: "ATE: 테스트 실패 원인 분석 및 heal 제안 평가",
204
+ description:
205
+ "ATE Feedback — Evaluate heal suggestions from a failed run and classify which fixes are safe to auto-apply. " +
206
+ "Safe-to-auto-apply: selector-map updates (CSS selector changes). " +
207
+ "Requires human review: contract schema changes, handler logic, route restructuring. " +
208
+ "Returns priority ranking of suggestions to guide review order.",
132
209
  inputSchema: {
133
210
  type: "object",
134
211
  properties: {
135
- repoRoot: { type: "string", description: "프로젝트 루트 디렉토리" },
136
- runId: { type: "string", description: "테스트 실행 ID" },
212
+ repoRoot: { type: "string", description: "Absolute path to the Mandu project root" },
213
+ runId: { type: "string", description: "Run ID with heal suggestions to evaluate" },
137
214
  autoApply: {
138
215
  type: "boolean",
139
- description: "자동 적용 가능 여부 (selector-map 안전)",
216
+ description: "If true, auto-apply only selector-map changes (CSS selectors) — other changes always require review",
140
217
  },
141
218
  },
142
219
  required: ["repoRoot", "runId"],
@@ -144,19 +221,23 @@ export const ateToolDefinitions: Tool[] = [
144
221
  },
145
222
  {
146
223
  name: "mandu.ate.apply_heal",
147
- description: "ATE: heal diff를 실제 코드에 적용 (rollback 가능)",
224
+ description:
225
+ "ATE Apply — Apply a specific heal suggestion diff to the codebase. " +
226
+ "Always creates a backup snapshot first (use mandu_rollback to undo). " +
227
+ "Run mandu.ate.feedback first to get the healIndex and confirm the fix is safe. " +
228
+ "After applying, re-run mandu.ate.run to verify the fix resolved the failure.",
148
229
  inputSchema: {
149
230
  type: "object",
150
231
  properties: {
151
- repoRoot: { type: "string", description: "프로젝트 루트 디렉토리" },
152
- runId: { type: "string", description: "테스트 실행 ID" },
232
+ repoRoot: { type: "string", description: "Absolute path to the Mandu project root" },
233
+ runId: { type: "string", description: "Run ID containing the heal suggestion to apply" },
153
234
  healIndex: {
154
235
  type: "number",
155
- description: "적용할 heal suggestion 인덱스 (0부터 시작)",
236
+ description: "0-based index of the heal suggestion to apply (from mandu.ate.heal or mandu.ate.feedback results)",
156
237
  },
157
238
  createBackup: {
158
239
  type: "boolean",
159
- description: "백업 생성 여부 (기본값: true, 필수 권장)",
240
+ description: "Create a snapshot before applying (default: true, strongly recommended — enables mandu_rollback)",
160
241
  },
161
242
  },
162
243
  required: ["repoRoot", "runId", "healIndex"],
@@ -26,7 +26,7 @@ import {
26
26
  generateJsonStatus,
27
27
  initializeArchitectureAnalyzer,
28
28
  getArchitectureAnalyzer,
29
- } from "../../../core/src/index.js";
29
+ } from "@mandujs/core";
30
30
  import { getProjectPaths } from "../utils/project.js";
31
31
 
32
32
  export const brainToolDefinitions: Tool[] = [
@@ -16,7 +16,15 @@ import fs from "fs/promises";
16
16
  export const contractToolDefinitions: Tool[] = [
17
17
  {
18
18
  name: "mandu_list_contracts",
19
- description: "List all contracts in the current Mandu project",
19
+ description:
20
+ "List all routes that have a contract module defined. " +
21
+ "In Mandu, a 'contract' is a Zod-based schema file (spec/contracts/{routeId}.contract.ts) that defines " +
22
+ "the request/response shape for an API route. Contracts enable: " +
23
+ "(1) automatic input validation and sanitization (strip/strict/passthrough normalize modes), " +
24
+ "(2) TypeScript type inference for slot handlers, " +
25
+ "(3) OpenAPI 3.0 spec generation via mandu_generate_openapi, " +
26
+ "(4) ATE L2 (schema validation) and L3 (full behavioral) test generation. " +
27
+ "Also returns a list of API routes that are missing contracts.",
20
28
  inputSchema: {
21
29
  type: "object",
22
30
  properties: {},
@@ -25,13 +33,17 @@ export const contractToolDefinitions: Tool[] = [
25
33
  },
26
34
  {
27
35
  name: "mandu_get_contract",
28
- description: "Get details of a specific contract by route ID",
36
+ description:
37
+ "Get the full TypeScript source of a contract file for a specific route. " +
38
+ "Returns the raw content of spec/contracts/{routeId}.contract.ts, " +
39
+ "which contains Zod schemas for each HTTP method's request body/query params and response shape. " +
40
+ "If the route has no contract, returns a suggestion to create one with mandu_create_contract.",
29
41
  inputSchema: {
30
42
  type: "object",
31
43
  properties: {
32
44
  routeId: {
33
45
  type: "string",
34
- description: "The route ID to retrieve contract for",
46
+ description: "The route ID to retrieve the contract for",
35
47
  },
36
48
  },
37
49
  required: ["routeId"],
@@ -39,22 +51,27 @@ export const contractToolDefinitions: Tool[] = [
39
51
  },
40
52
  {
41
53
  name: "mandu_create_contract",
42
- description: "Create a new contract for a route",
54
+ description:
55
+ "Create a new contract file for a route and link it in the manifest. " +
56
+ "Generates spec/contracts/{routeId}.contract.ts with Zod schema stubs for each HTTP method. " +
57
+ "Template includes: request schema (body for POST/PUT/PATCH, query for GET/DELETE) and response schema. " +
58
+ "After creation: edit the Zod schemas to match your actual API shape, " +
59
+ "then run mandu_generate to regenerate typed handlers with validation.",
43
60
  inputSchema: {
44
61
  type: "object",
45
62
  properties: {
46
63
  routeId: {
47
64
  type: "string",
48
- description: "The route ID to create contract for",
65
+ description: "The route ID to create a contract for",
49
66
  },
50
67
  description: {
51
68
  type: "string",
52
- description: "API description (optional)",
69
+ description: "Human-readable API description added as a comment in the contract file",
53
70
  },
54
71
  methods: {
55
72
  type: "array",
56
73
  items: { type: "string" },
57
- description: "HTTP methods to include (default: route methods or ['GET', 'POST'])",
74
+ description: "HTTP methods to generate schemas for (default: route's declared methods or ['GET', 'POST'])",
58
75
  },
59
76
  },
60
77
  required: ["routeId"],
@@ -62,7 +79,11 @@ export const contractToolDefinitions: Tool[] = [
62
79
  },
63
80
  {
64
81
  name: "mandu_update_route_contract",
65
- description: "Update a route to add or change its contract module",
82
+ description:
83
+ "Update the manifest to link an existing contract file to a route. " +
84
+ "Use this when the contract file already exists but the manifest's contractModule path needs updating, " +
85
+ "or when moving a contract file to a new location. " +
86
+ "Does not modify the contract file itself — only updates the manifest reference and lock file.",
66
87
  inputSchema: {
67
88
  type: "object",
68
89
  properties: {
@@ -72,7 +93,7 @@ export const contractToolDefinitions: Tool[] = [
72
93
  },
73
94
  contractModule: {
74
95
  type: "string",
75
- description: "Path to contract file (e.g., spec/contracts/users.contract.ts)",
96
+ description: "Relative path to the contract file from project root (e.g., spec/contracts/users.contract.ts)",
76
97
  },
77
98
  },
78
99
  required: ["routeId", "contractModule"],
@@ -80,7 +101,12 @@ export const contractToolDefinitions: Tool[] = [
80
101
  },
81
102
  {
82
103
  name: "mandu_validate_contracts",
83
- description: "Validate all contracts against their slot implementations",
104
+ description:
105
+ "Validate all contracts against their linked slot implementations for consistency. " +
106
+ "Checks that every HTTP method defined in a contract has a matching handler in the slot, " +
107
+ "response types are compatible, and no orphaned contracts exist. " +
108
+ "Run this after modifying contracts or slots, or before running ATE tests to catch mismatches early. " +
109
+ "Returns a list of violations with file locations, descriptions, and fix suggestions.",
84
110
  inputSchema: {
85
111
  type: "object",
86
112
  properties: {},
@@ -89,18 +115,27 @@ export const contractToolDefinitions: Tool[] = [
89
115
  },
90
116
  {
91
117
  name: "mandu_sync_contract_slot",
92
- description: "Sync contract and slot to resolve mismatches",
118
+ description:
119
+ "Detect and generate code to resolve HTTP method mismatches between a contract and its slot. " +
120
+ "'contract-to-slot': finds HTTP methods defined in the contract but missing from the slot — " +
121
+ "generates handler stub code to add to the slot file. " +
122
+ "'slot-to-contract': finds slot handlers not documented in the contract — " +
123
+ "generates Zod schema stubs to add to the contract. " +
124
+ "Returns generated code snippets to review — does NOT auto-write files. " +
125
+ "Copy the output and use the Edit tool to apply the changes.",
93
126
  inputSchema: {
94
127
  type: "object",
95
128
  properties: {
96
129
  routeId: {
97
130
  type: "string",
98
- description: "The route ID to sync",
131
+ description: "The route ID to sync (must have both contractModule and slotModule)",
99
132
  },
100
133
  direction: {
101
134
  type: "string",
102
135
  enum: ["contract-to-slot", "slot-to-contract"],
103
- description: "Direction of sync: contract-to-slot adds slot stubs, slot-to-contract adds contract schemas",
136
+ description:
137
+ "'contract-to-slot': generate slot handler stubs for undocumented contract methods. " +
138
+ "'slot-to-contract': generate contract schema stubs for undocumented slot handlers.",
104
139
  },
105
140
  },
106
141
  required: ["routeId", "direction"],
@@ -108,21 +143,25 @@ export const contractToolDefinitions: Tool[] = [
108
143
  },
109
144
  {
110
145
  name: "mandu_generate_openapi",
111
- description: "Generate OpenAPI 3.0 specification from contracts",
146
+ description:
147
+ "Generate an OpenAPI 3.0 specification JSON file from all routes with contract modules. " +
148
+ "Only routes with a defined contractModule are included — add contracts with mandu_create_contract first. " +
149
+ "Output is written to openapi.json (or a custom path). " +
150
+ "The generated spec can be served with Swagger UI, Redoc, or imported into any OpenAPI-compatible tooling.",
112
151
  inputSchema: {
113
152
  type: "object",
114
153
  properties: {
115
154
  output: {
116
155
  type: "string",
117
- description: "Output file path (default: openapi.json)",
156
+ description: "Output file path relative to project root (default: openapi.json)",
118
157
  },
119
158
  title: {
120
159
  type: "string",
121
- description: "API title (default: Mandu API)",
160
+ description: "API title shown in the spec (default: 'Mandu API')",
122
161
  },
123
162
  version: {
124
163
  type: "string",
125
- description: "API version (default: from manifest)",
164
+ description: "API version string (default: taken from the manifest version)",
126
165
  },
127
166
  },
128
167
  required: [],
@@ -8,17 +8,27 @@ export const generateToolDefinitions: Tool[] = [
8
8
  {
9
9
  name: "mandu_generate",
10
10
  description:
11
- "Generate route handlers, components, and resource artifacts. Creates server handlers, page components, slot files, and resource CRUD operations.",
11
+ "Generate all Mandu framework artifacts from the current routes manifest and resource schemas. " +
12
+ "Runs two generation steps: " +
13
+ "(1) Route generation: for every route in .mandu/routes.manifest.json, creates " +
14
+ "a server-side handler in .mandu/generated/server/{routeId}.route.ts and " +
15
+ "a web component in .mandu/generated/web/{routeId}.route.tsx. " +
16
+ "These generated files wire up slots and contracts automatically — do NOT edit them directly. " +
17
+ "Instead, edit source files in app/ (route definition) or spec/ (slots, contracts). " +
18
+ "(2) Resource generation (resources=true, default): scans spec/resources/{name}/schema.ts " +
19
+ "and generates CRUD boilerplate (repository, service, handlers) for each declared resource. " +
20
+ "Run this after adding routes, modifying slot/contract files, or changing resource schemas. " +
21
+ "Use dryRun=true to preview what would be created or overwritten without writing any files.",
12
22
  inputSchema: {
13
23
  type: "object",
14
24
  properties: {
15
25
  dryRun: {
16
26
  type: "boolean",
17
- description: "If true, show what would be generated without writing files",
27
+ description: "Preview what would be generated without writing files (default: false)",
18
28
  },
19
29
  resources: {
20
30
  type: "boolean",
21
- description: "Include resource artifact generation (default: true)",
31
+ description: "Include resource artifact generation from spec/resources/ (default: true)",
22
32
  },
23
33
  },
24
34
  required: [],
@@ -26,7 +36,11 @@ export const generateToolDefinitions: Tool[] = [
26
36
  },
27
37
  {
28
38
  name: "mandu_generate_status",
29
- description: "Get the current generation status and generated file map",
39
+ description:
40
+ "Show the current state of all generated artifacts from .mandu/generated.map.json. " +
41
+ "Returns: generation timestamp, source spec version, total file count, " +
42
+ "and a list of generated files per route with their kinds (server handler, web component, slot stub). " +
43
+ "If no generated.map.json exists, prompts to run mandu_generate first.",
30
44
  inputSchema: {
31
45
  type: "object",
32
46
  properties: {},