@mandujs/mcp 0.18.6 → 0.18.8
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 +3 -3
- package/src/adapters/tool-adapter.ts +4 -4
- package/src/executor/tool-executor.ts +2 -1
- package/src/hooks/config-watcher.ts +3 -3
- package/src/registry/mcp-tool-registry.ts +1 -1
- package/src/server.ts +3 -2
- package/src/tools/ate.ts +81 -17
- package/src/tools/brain.ts +1 -1
- package/src/tools/contract.ts +2 -1
- package/src/tools/guard.ts +1 -2
- package/src/tools/hydration.ts +6 -5
- package/src/tools/index.ts +3 -2
- package/src/tools/seo.ts +2 -2
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mandujs/mcp",
|
|
3
|
-
"version": "0.18.
|
|
3
|
+
"version": "0.18.8",
|
|
4
4
|
"description": "Mandu MCP Server - Agent-native interface for Mandu framework operations",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./src/index.ts",
|
|
@@ -32,8 +32,8 @@
|
|
|
32
32
|
"access": "public"
|
|
33
33
|
},
|
|
34
34
|
"dependencies": {
|
|
35
|
-
"@mandujs/core": "^0.18.
|
|
36
|
-
"@mandujs/ate": "^0.17.
|
|
35
|
+
"@mandujs/core": "^0.18.22",
|
|
36
|
+
"@mandujs/ate": "^0.17.2",
|
|
37
37
|
"@modelcontextprotocol/sdk": "^1.25.3"
|
|
38
38
|
},
|
|
39
39
|
"engines": {
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
import type { Tool } from "@modelcontextprotocol/sdk/types.js";
|
|
8
|
-
import type { McpToolPlugin } from "@mandujs/core";
|
|
8
|
+
import type { McpToolPlugin } from "@mandujs/core/plugins";
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
11
|
* MCP SDK Tool을 McpToolPlugin으로 변환
|
|
@@ -25,8 +25,8 @@ export function toolToPlugin(
|
|
|
25
25
|
return {
|
|
26
26
|
name: definition.name,
|
|
27
27
|
description: definition.description ?? "",
|
|
28
|
-
inputSchema: definition.inputSchema as Record<string, unknown>,
|
|
29
|
-
execute: handler
|
|
28
|
+
inputSchema: definition.inputSchema as unknown as Record<string, unknown>,
|
|
29
|
+
execute: handler as (input: unknown) => Promise<unknown>,
|
|
30
30
|
};
|
|
31
31
|
}
|
|
32
32
|
|
|
@@ -37,7 +37,7 @@ export function pluginToTool(plugin: McpToolPlugin): Tool {
|
|
|
37
37
|
return {
|
|
38
38
|
name: plugin.name,
|
|
39
39
|
description: plugin.description,
|
|
40
|
-
inputSchema: plugin.inputSchema,
|
|
40
|
+
inputSchema: plugin.inputSchema as Tool["inputSchema"],
|
|
41
41
|
};
|
|
42
42
|
}
|
|
43
43
|
|
|
@@ -4,7 +4,8 @@
|
|
|
4
4
|
* 도구 실행 + 훅 + 에러 처리 통합
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import type { McpToolPlugin
|
|
7
|
+
import type { McpToolPlugin } from "@mandujs/core/plugins";
|
|
8
|
+
import type { ManduConfig } from "@mandujs/core";
|
|
8
9
|
import { mcpToolRegistry } from "../registry/mcp-tool-registry.js";
|
|
9
10
|
import { mcpHookRegistry, type McpToolContext } from "../hooks/mcp-hooks.js";
|
|
10
11
|
import { createToolResponse, logToolError, type McpToolResponse } from "./error-handler.js";
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
import type { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
8
|
-
import { watchConfig, hasConfigChanged, type ManduConfig } from "@mandujs/core";
|
|
8
|
+
import { watchConfig, hasConfigChanged, getChangedSections, type ManduConfig } from "@mandujs/core";
|
|
9
9
|
import { mcpToolRegistry } from "../registry/mcp-tool-registry.js";
|
|
10
10
|
|
|
11
11
|
/**
|
|
@@ -75,7 +75,7 @@ export async function startMcpConfigWatcher(
|
|
|
75
75
|
logger: "mandu-config",
|
|
76
76
|
data: {
|
|
77
77
|
type: "config_reload",
|
|
78
|
-
changedSections: event.
|
|
78
|
+
changedSections: getChangedSections(event.previous, event.current),
|
|
79
79
|
path: event.path,
|
|
80
80
|
},
|
|
81
81
|
});
|
|
@@ -86,7 +86,7 @@ export async function startMcpConfigWatcher(
|
|
|
86
86
|
|
|
87
87
|
// MCP 관련 설정 변경 확인
|
|
88
88
|
if (event.previous && event.current) {
|
|
89
|
-
if (
|
|
89
|
+
if (needsToolReregistration(event.previous, event.current)) {
|
|
90
90
|
// MCP 설정 변경 시 도구 재초기화 등 필요한 작업
|
|
91
91
|
if (server) {
|
|
92
92
|
try {
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
import type { Tool } from "@modelcontextprotocol/sdk/types.js";
|
|
11
|
-
import type { McpToolPlugin } from "@mandujs/core";
|
|
11
|
+
import type { McpToolPlugin } from "@mandujs/core/plugins";
|
|
12
12
|
import { pluginToTool } from "../adapters/tool-adapter.js";
|
|
13
13
|
|
|
14
14
|
/**
|
package/src/server.ts
CHANGED
|
@@ -16,6 +16,7 @@ import {
|
|
|
16
16
|
ListToolsRequestSchema,
|
|
17
17
|
ListResourcesRequestSchema,
|
|
18
18
|
ReadResourceRequestSchema,
|
|
19
|
+
type CallToolResult,
|
|
19
20
|
} from "@modelcontextprotocol/sdk/types.js";
|
|
20
21
|
|
|
21
22
|
import { loadManduConfig, startWatcher, type ManduConfig } from "@mandujs/core";
|
|
@@ -113,13 +114,13 @@ export class ManduMcpServer {
|
|
|
113
114
|
});
|
|
114
115
|
|
|
115
116
|
// 도구 실행 요청
|
|
116
|
-
this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
117
|
+
this.server.setRequestHandler(CallToolRequestSchema, async (request, _extra) => {
|
|
117
118
|
const { name, arguments: args } = request.params;
|
|
118
119
|
|
|
119
120
|
// DNA-007 + DNA-016: Tool Executor로 실행
|
|
120
121
|
const result = await this.toolExecutor.execute(name, args || {});
|
|
121
122
|
|
|
122
|
-
return result.response;
|
|
123
|
+
return result.response as unknown as CallToolResult;
|
|
123
124
|
});
|
|
124
125
|
}
|
|
125
126
|
|
package/src/tools/ate.ts
CHANGED
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
analyzeFeedback,
|
|
11
11
|
applyHeal,
|
|
12
12
|
} from "@mandujs/ate";
|
|
13
|
+
import type { OracleLevel } from "@mandujs/ate";
|
|
13
14
|
|
|
14
15
|
export const ateToolDefinitions: Tool[] = [
|
|
15
16
|
{
|
|
@@ -248,38 +249,95 @@ export const ateToolDefinitions: Tool[] = [
|
|
|
248
249
|
export function ateTools(projectRoot: string) {
|
|
249
250
|
return {
|
|
250
251
|
"mandu.ate.extract": async (args: Record<string, unknown>) => {
|
|
251
|
-
|
|
252
|
+
const { repoRoot, tsconfigPath, routeGlobs, buildSalt } = args as {
|
|
253
|
+
repoRoot: string;
|
|
254
|
+
tsconfigPath?: string;
|
|
255
|
+
routeGlobs?: string[];
|
|
256
|
+
buildSalt?: string;
|
|
257
|
+
};
|
|
258
|
+
return await ateExtract({ repoRoot, tsconfigPath, routeGlobs, buildSalt });
|
|
252
259
|
},
|
|
253
260
|
"mandu.ate.generate": async (args: Record<string, unknown>) => {
|
|
254
|
-
|
|
261
|
+
const { repoRoot, oracleLevel, onlyRoutes } = args as {
|
|
262
|
+
repoRoot: string;
|
|
263
|
+
oracleLevel?: OracleLevel;
|
|
264
|
+
onlyRoutes?: string[];
|
|
265
|
+
};
|
|
266
|
+
return ateGenerate({ repoRoot, oracleLevel, onlyRoutes });
|
|
255
267
|
},
|
|
256
268
|
"mandu.ate.run": async (args: Record<string, unknown>) => {
|
|
257
|
-
|
|
269
|
+
const { repoRoot, baseURL, ci, headless, browsers } = args as {
|
|
270
|
+
repoRoot: string;
|
|
271
|
+
baseURL?: string;
|
|
272
|
+
ci?: boolean;
|
|
273
|
+
headless?: boolean;
|
|
274
|
+
browsers?: ("chromium" | "firefox" | "webkit")[];
|
|
275
|
+
};
|
|
276
|
+
return await ateRun({ repoRoot, baseURL, ci, headless, browsers });
|
|
258
277
|
},
|
|
259
278
|
"mandu.ate.report": async (args: Record<string, unknown>) => {
|
|
260
|
-
const
|
|
279
|
+
const { repoRoot, runId, startedAt, finishedAt, exitCode, oracleLevel, format, impact } = args as {
|
|
280
|
+
repoRoot: string;
|
|
281
|
+
runId: string;
|
|
282
|
+
startedAt: string;
|
|
283
|
+
finishedAt: string;
|
|
284
|
+
exitCode: number;
|
|
285
|
+
oracleLevel?: OracleLevel;
|
|
286
|
+
format?: "json" | "html" | "both";
|
|
287
|
+
impact?: { changedFiles: string[]; selectedRoutes: string[]; mode: "full" | "subset" };
|
|
288
|
+
};
|
|
261
289
|
return await ateReport({
|
|
262
|
-
repoRoot
|
|
263
|
-
runId
|
|
264
|
-
startedAt
|
|
265
|
-
finishedAt
|
|
266
|
-
exitCode
|
|
267
|
-
oracleLevel:
|
|
268
|
-
format:
|
|
269
|
-
impact
|
|
290
|
+
repoRoot,
|
|
291
|
+
runId,
|
|
292
|
+
startedAt,
|
|
293
|
+
finishedAt,
|
|
294
|
+
exitCode,
|
|
295
|
+
oracleLevel: oracleLevel ?? "L1",
|
|
296
|
+
format: format ?? "both",
|
|
297
|
+
impact,
|
|
270
298
|
});
|
|
271
299
|
},
|
|
272
300
|
"mandu.ate.heal": async (args: Record<string, unknown>) => {
|
|
273
|
-
|
|
301
|
+
const { repoRoot, runId } = args as { repoRoot: string; runId: string };
|
|
302
|
+
return ateHeal({ repoRoot, runId });
|
|
274
303
|
},
|
|
275
304
|
"mandu.ate.impact": async (args: Record<string, unknown>) => {
|
|
276
|
-
|
|
305
|
+
const { repoRoot, base, head } = args as {
|
|
306
|
+
repoRoot: string;
|
|
307
|
+
base?: string;
|
|
308
|
+
head?: string;
|
|
309
|
+
};
|
|
310
|
+
return ateImpact({ repoRoot, base, head });
|
|
277
311
|
},
|
|
278
312
|
"mandu.ate.auto_pipeline": async (args: Record<string, unknown>) => {
|
|
279
|
-
|
|
313
|
+
const {
|
|
314
|
+
repoRoot, baseURL, oracleLevel, ci, useImpactAnalysis,
|
|
315
|
+
base, head, autoHeal, tsconfigPath, routeGlobs, buildSalt,
|
|
316
|
+
} = args as {
|
|
317
|
+
repoRoot: string;
|
|
318
|
+
baseURL?: string;
|
|
319
|
+
oracleLevel?: OracleLevel;
|
|
320
|
+
ci?: boolean;
|
|
321
|
+
useImpactAnalysis?: boolean;
|
|
322
|
+
base?: string;
|
|
323
|
+
head?: string;
|
|
324
|
+
autoHeal?: boolean;
|
|
325
|
+
tsconfigPath?: string;
|
|
326
|
+
routeGlobs?: string[];
|
|
327
|
+
buildSalt?: string;
|
|
328
|
+
};
|
|
329
|
+
return await runFullPipeline({
|
|
330
|
+
repoRoot, baseURL, oracleLevel, ci, useImpactAnalysis,
|
|
331
|
+
base, head, autoHeal, tsconfigPath, routeGlobs, buildSalt,
|
|
332
|
+
});
|
|
280
333
|
},
|
|
281
334
|
"mandu.ate.feedback": async (args: Record<string, unknown>) => {
|
|
282
|
-
const
|
|
335
|
+
const { repoRoot, runId, autoApply } = args as {
|
|
336
|
+
repoRoot: string;
|
|
337
|
+
runId: string;
|
|
338
|
+
autoApply?: boolean;
|
|
339
|
+
};
|
|
340
|
+
const result = analyzeFeedback({ repoRoot, runId, autoApply });
|
|
283
341
|
return {
|
|
284
342
|
ok: true,
|
|
285
343
|
category: result.category,
|
|
@@ -290,7 +348,13 @@ export function ateTools(projectRoot: string) {
|
|
|
290
348
|
};
|
|
291
349
|
},
|
|
292
350
|
"mandu.ate.apply_heal": async (args: Record<string, unknown>) => {
|
|
293
|
-
const
|
|
351
|
+
const { repoRoot, runId, healIndex, createBackup } = args as {
|
|
352
|
+
repoRoot: string;
|
|
353
|
+
runId: string;
|
|
354
|
+
healIndex: number;
|
|
355
|
+
createBackup?: boolean;
|
|
356
|
+
};
|
|
357
|
+
const result = applyHeal({ repoRoot, runId, healIndex, createBackup });
|
|
294
358
|
return {
|
|
295
359
|
ok: result.success,
|
|
296
360
|
...result,
|
package/src/tools/brain.ts
CHANGED
|
@@ -198,7 +198,7 @@ export function brainTools(projectRoot: string, server?: Server, monitor?: Activ
|
|
|
198
198
|
file: p.file,
|
|
199
199
|
type: p.type,
|
|
200
200
|
description: p.description,
|
|
201
|
-
command: p.command,
|
|
201
|
+
...(p.type === "command" ? { command: p.command } : {}),
|
|
202
202
|
confidence: p.confidence,
|
|
203
203
|
})),
|
|
204
204
|
nextCommand: analysis.nextCommand,
|
package/src/tools/contract.ts
CHANGED
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
openAPIToJSON,
|
|
9
9
|
type RouteSpec,
|
|
10
10
|
type RoutesManifest,
|
|
11
|
+
type SpecHttpMethod,
|
|
11
12
|
} from "@mandujs/core";
|
|
12
13
|
import { getProjectPaths, readJsonFile, writeJsonFile } from "../utils/project.js";
|
|
13
14
|
import path from "path";
|
|
@@ -295,7 +296,7 @@ export function contractTools(projectRoot: string) {
|
|
|
295
296
|
// Generate contract with custom methods if provided
|
|
296
297
|
const routeWithMethods: RouteSpec = {
|
|
297
298
|
...route,
|
|
298
|
-
methods: methods as
|
|
299
|
+
methods: (methods as SpecHttpMethod[] | undefined) || route.methods || ["GET", "POST"],
|
|
299
300
|
};
|
|
300
301
|
|
|
301
302
|
const contractContent = generateContractTemplate(routeWithMethods);
|
package/src/tools/guard.ts
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import type { Tool } from "@modelcontextprotocol/sdk/types.js";
|
|
2
|
+
import { ErrorClassifier, type ManduError } from "@mandujs/core/error";
|
|
2
3
|
import {
|
|
3
4
|
loadManifest,
|
|
4
5
|
runGuardCheck,
|
|
5
6
|
runAutoCorrect,
|
|
6
|
-
ErrorClassifier,
|
|
7
|
-
type ManduError,
|
|
8
7
|
type GeneratedMap,
|
|
9
8
|
// Self-Healing Guard imports
|
|
10
9
|
checkWithHealing,
|
package/src/tools/hydration.ts
CHANGED
|
@@ -6,8 +6,9 @@ import {
|
|
|
6
6
|
needsHydration,
|
|
7
7
|
getRouteHydration,
|
|
8
8
|
type BundleManifest,
|
|
9
|
-
type
|
|
9
|
+
type SpecHydrationStrategy,
|
|
10
10
|
type HydrationPriority,
|
|
11
|
+
type HydrationConfig,
|
|
11
12
|
} from "@mandujs/core";
|
|
12
13
|
import { getProjectPaths, readJsonFile, writeJsonFile } from "../utils/project.js";
|
|
13
14
|
import path from "path";
|
|
@@ -238,7 +239,7 @@ export function hydrationTools(projectRoot: string) {
|
|
|
238
239
|
mandu_set_hydration: async (args: Record<string, unknown>) => {
|
|
239
240
|
const { routeId, strategy, priority, preload } = args as {
|
|
240
241
|
routeId: string;
|
|
241
|
-
strategy?:
|
|
242
|
+
strategy?: SpecHydrationStrategy;
|
|
242
243
|
priority?: HydrationPriority;
|
|
243
244
|
preload?: boolean;
|
|
244
245
|
};
|
|
@@ -263,7 +264,7 @@ export function hydrationTools(projectRoot: string) {
|
|
|
263
264
|
}
|
|
264
265
|
|
|
265
266
|
// Update hydration config
|
|
266
|
-
const currentHydration = route.hydration || {};
|
|
267
|
+
const currentHydration: Partial<HydrationConfig> = route.hydration || {};
|
|
267
268
|
const newHydration = {
|
|
268
269
|
strategy: strategy || currentHydration.strategy || "island",
|
|
269
270
|
priority: priority || currentHydration.priority || "visible",
|
|
@@ -297,7 +298,7 @@ export function hydrationTools(projectRoot: string) {
|
|
|
297
298
|
mandu_add_client_slot: async (args: Record<string, unknown>) => {
|
|
298
299
|
const { routeId, strategy = "island", priority = "visible" } = args as {
|
|
299
300
|
routeId: string;
|
|
300
|
-
strategy?:
|
|
301
|
+
strategy?: SpecHydrationStrategy;
|
|
301
302
|
priority?: HydrationPriority;
|
|
302
303
|
};
|
|
303
304
|
|
|
@@ -349,7 +350,7 @@ export function hydrationTools(projectRoot: string) {
|
|
|
349
350
|
...route,
|
|
350
351
|
clientModule: clientModulePath,
|
|
351
352
|
hydration: {
|
|
352
|
-
strategy: strategy as
|
|
353
|
+
strategy: strategy as SpecHydrationStrategy,
|
|
353
354
|
priority: priority as HydrationPriority,
|
|
354
355
|
preload: false,
|
|
355
356
|
},
|
package/src/tools/index.ts
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
* 도구 정의 및 레지스트리 등록
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
+
import type { Tool } from "@modelcontextprotocol/sdk/types.js";
|
|
7
8
|
import type { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
8
9
|
import type { ActivityMonitor } from "../activity-monitor.js";
|
|
9
10
|
import { mcpToolRegistry } from "../registry/mcp-tool-registry.js";
|
|
@@ -48,7 +49,7 @@ import { componentTools, componentToolDefinitions } from "./component.js";
|
|
|
48
49
|
*/
|
|
49
50
|
interface ToolModule {
|
|
50
51
|
category: string;
|
|
51
|
-
definitions:
|
|
52
|
+
definitions: Tool[];
|
|
52
53
|
handlers: (
|
|
53
54
|
projectRoot: string,
|
|
54
55
|
server?: Server,
|
|
@@ -73,7 +74,7 @@ const TOOL_MODULES: ToolModule[] = [
|
|
|
73
74
|
{ category: "runtime", definitions: runtimeToolDefinitions, handlers: runtimeTools },
|
|
74
75
|
{ category: "seo", definitions: seoToolDefinitions, handlers: seoTools },
|
|
75
76
|
{ category: "project", definitions: projectToolDefinitions, handlers: projectTools as ToolModule["handlers"], requiresServer: true },
|
|
76
|
-
{ category: "ate", definitions: ateToolDefinitions
|
|
77
|
+
{ category: "ate", definitions: ateToolDefinitions, handlers: ateTools as ToolModule["handlers"] },
|
|
77
78
|
{ category: "resource", definitions: resourceToolDefinitions, handlers: resourceTools },
|
|
78
79
|
{ category: "component", definitions: componentToolDefinitions, handlers: componentTools },
|
|
79
80
|
];
|
package/src/tools/seo.ts
CHANGED
|
@@ -247,10 +247,10 @@ export function seoTools(projectRoot: string) {
|
|
|
247
247
|
jsonLd = createOrganizationJsonLd(data as Parameters<typeof createOrganizationJsonLd>[0]);
|
|
248
248
|
break;
|
|
249
249
|
case "Breadcrumb":
|
|
250
|
-
jsonLd = createBreadcrumbJsonLd(data as Array<{ name: string; url: string }>);
|
|
250
|
+
jsonLd = createBreadcrumbJsonLd(data as unknown as Array<{ name: string; url: string }>);
|
|
251
251
|
break;
|
|
252
252
|
case "FAQ":
|
|
253
|
-
jsonLd = createFAQJsonLd(data as Array<{ question: string; answer: string }>);
|
|
253
|
+
jsonLd = createFAQJsonLd(data as unknown as Array<{ question: string; answer: string }>);
|
|
254
254
|
break;
|
|
255
255
|
case "Product":
|
|
256
256
|
jsonLd = createProductJsonLd(data as Parameters<typeof createProductJsonLd>[0]);
|