@mandujs/mcp 0.21.0 → 0.22.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mandujs/mcp",
3
- "version": "0.21.0",
3
+ "version": "0.22.0",
4
4
  "description": "Mandu MCP Server - Agent-native interface for Mandu framework operations",
5
5
  "type": "module",
6
6
  "main": "./src/index.ts",
@@ -34,9 +34,9 @@
34
34
  "access": "public"
35
35
  },
36
36
  "dependencies": {
37
- "@mandujs/core": "^0.31.0",
37
+ "@mandujs/core": "^0.33.0",
38
38
  "@mandujs/ate": "^0.19.1",
39
- "@mandujs/skills": "^10.0.0",
39
+ "@mandujs/skills": "^12.0.0",
40
40
  "@modelcontextprotocol/sdk": "^1.25.3"
41
41
  },
42
42
  "engines": {
@@ -13,6 +13,7 @@ import { kitchenTools } from "./kitchen.js";
13
13
  import { ateTools } from "./ate.js";
14
14
  import { requestRuntimeCache } from "../utils/runtime-control.js";
15
15
  import { requireLock } from "../tx-lock.js";
16
+ import { runExtendedDiagnose, buildReport, type DiagnoseCheckResult } from "@mandujs/core/diagnose";
16
17
  import path from "path";
17
18
  import fs from "fs/promises";
18
19
 
@@ -43,7 +44,11 @@ export const compositeToolDefinitions: Tool[] = [
43
44
  name: "mandu.diagnose",
44
45
  description:
45
46
  "Run all diagnostic checks in parallel and return a unified health report. " +
46
- "Combines: kitchen_errors + guard_check + validate_contracts + validate_manifest.",
47
+ "Legacy checks: kitchen_errors + guard_check + validate_contracts + validate_manifest. " +
48
+ "Extended checks (Issue #215): manifest_freshness, prerender_pollution, cloneelement_warnings, " +
49
+ "dev_artifacts_in_prod, package_export_gaps. Every check uses the unified " +
50
+ "{ ok, rule, severity, message, suggestion?, details? } shape. " +
51
+ "`healthy: false` when any check has severity='error'; warnings do not block.",
47
52
  annotations: {
48
53
  readOnlyHint: true,
49
54
  },
@@ -251,25 +256,78 @@ export function compositeTools(projectRoot: string) {
251
256
 
252
257
  "mandu.diagnose": async (args: Record<string, unknown>) => {
253
258
  const { autoFix = false } = args as { autoFix?: boolean };
254
- const [kitchenResult, guardResult, contractResult, manifestResult] = await Promise.all([
259
+
260
+ // Run legacy (structural) checks + extended (#215) checks in parallel.
261
+ const [kitchenResult, guardResult, contractResult, manifestResult, extendedReport] = await Promise.all([
255
262
  kitchen["mandu.kitchen.errors"]({ clear: false }).catch((e: Error) => ({ error: e.message })),
256
263
  guard["mandu.guard.check"]({ autoCorrect: autoFix }).catch((e: Error) => ({ error: e.message })),
257
264
  contract["mandu.contract.validate"]({}).catch((e: Error) => ({ error: e.message })),
258
265
  spec["mandu.manifest.validate"]({}).catch((e: Error) => ({ error: e.message })),
266
+ runExtendedDiagnose(projectRoot).catch((e: Error) => ({
267
+ healthy: false,
268
+ errorCount: 1,
269
+ warningCount: 0,
270
+ checks: [{ ok: false, rule: "diagnose_internal_error", severity: "error" as const, message: e.message }],
271
+ summary: { total: 1, passed: 0, failed: 1 },
272
+ })),
259
273
  ]);
260
- const checks = [
261
- { name: "kitchen_errors", result: kitchenResult },
262
- { name: "guard_check", result: guardResult },
263
- { name: "contract_validation", result: contractResult },
264
- { name: "manifest_validation", result: manifestResult },
265
- ];
266
- const isFail = (c: typeof checks[number]) => {
267
- const r = c.result as Record<string, unknown>;
268
- return r.error || r.passed === false || r.valid === false;
274
+
275
+ // Normalize each legacy check into the unified shape.
276
+ const normalizeLegacy = (rule: string, result: unknown): DiagnoseCheckResult => {
277
+ const r = (typeof result === "object" && result !== null) ? result as Record<string, unknown> : {};
278
+ const errorMsg = typeof r.error === "string" ? r.error : undefined;
279
+ const failed =
280
+ !!errorMsg || r.passed === false || r.valid === false;
281
+ if (!failed) {
282
+ return {
283
+ ok: true,
284
+ rule,
285
+ message: `${rule} passed`,
286
+ details: r,
287
+ };
288
+ }
289
+ return {
290
+ ok: false,
291
+ rule,
292
+ severity: "error",
293
+ message: errorMsg ?? `${rule} failed`,
294
+ details: r,
295
+ };
269
296
  };
297
+
298
+ const legacyChecks: DiagnoseCheckResult[] = [
299
+ normalizeLegacy("kitchen_errors", kitchenResult),
300
+ normalizeLegacy("guard_check", guardResult),
301
+ normalizeLegacy("contract_validation", contractResult),
302
+ normalizeLegacy("manifest_validation", manifestResult),
303
+ ];
304
+
305
+ // Tighten manifest_validation by cross-checking against the fresh
306
+ // bundle-manifest check. Legacy manifest_validation only inspects
307
+ // the FS-routes manifest; it passes even when the bundle manifest
308
+ // is stale (the #211 gap). If manifest_freshness is unhealthy,
309
+ // legacy manifest_validation's pass is misleading — downgrade it.
310
+ const freshness = extendedReport.checks.find((c) => c.rule === "manifest_freshness");
311
+ if (freshness && !freshness.ok && freshness.severity === "error") {
312
+ const legacyMv = legacyChecks.find((c) => c.rule === "manifest_validation");
313
+ if (legacyMv && legacyMv.ok) {
314
+ legacyMv.ok = false;
315
+ legacyMv.severity = "warning";
316
+ legacyMv.message = "FS-routes manifest loaded, but bundle manifest is stale (see manifest_freshness).";
317
+ legacyMv.suggestion = "Run `mandu build` to regenerate the bundle manifest.";
318
+ }
319
+ }
320
+
321
+ const allChecks: DiagnoseCheckResult[] = [...legacyChecks, ...extendedReport.checks];
322
+ const report = buildReport(allChecks);
323
+
270
324
  return {
271
- healthy: !checks.some(isFail), autoFix, checks,
272
- summary: { total: checks.length, passed: checks.filter((c) => !isFail(c)).length, failed: checks.filter(isFail).length },
325
+ healthy: report.healthy,
326
+ autoFix,
327
+ errorCount: report.errorCount,
328
+ warningCount: report.warningCount,
329
+ checks: report.checks,
330
+ summary: report.summary,
273
331
  };
274
332
  },
275
333