@godot-mcp/mcp-server 0.0.0 → 0.1.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/LICENSE +21 -0
- package/README.md +105 -2
- package/dist/createServer.d.ts +20 -0
- package/dist/createServer.d.ts.map +1 -0
- package/dist/createServer.js +46 -0
- package/dist/createServer.js.map +1 -0
- package/dist/executeTool.d.ts +40 -0
- package/dist/executeTool.d.ts.map +1 -0
- package/dist/executeTool.js +109 -0
- package/dist/executeTool.js.map +1 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +12 -0
- package/dist/index.js.map +1 -0
- package/dist/registerCoreTools.d.ts +25 -0
- package/dist/registerCoreTools.d.ts.map +1 -0
- package/dist/registerCoreTools.js +88 -0
- package/dist/registerCoreTools.js.map +1 -0
- package/dist/registerEditorTools.d.ts +12 -0
- package/dist/registerEditorTools.d.ts.map +1 -0
- package/dist/registerEditorTools.js +59 -0
- package/dist/registerEditorTools.js.map +1 -0
- package/dist/registerExtensionTools.d.ts +9 -0
- package/dist/registerExtensionTools.d.ts.map +1 -0
- package/dist/registerExtensionTools.js +59 -0
- package/dist/registerExtensionTools.js.map +1 -0
- package/dist/registerInputTools.d.ts +11 -0
- package/dist/registerInputTools.d.ts.map +1 -0
- package/dist/registerInputTools.js +20 -0
- package/dist/registerInputTools.js.map +1 -0
- package/dist/registerProjectTools.d.ts +12 -0
- package/dist/registerProjectTools.d.ts.map +1 -0
- package/dist/registerProjectTools.js +54 -0
- package/dist/registerProjectTools.js.map +1 -0
- package/dist/registerRuntimeTools.d.ts +34 -0
- package/dist/registerRuntimeTools.d.ts.map +1 -0
- package/dist/registerRuntimeTools.js +147 -0
- package/dist/registerRuntimeTools.js.map +1 -0
- package/dist/registerUnsafeTools.d.ts +12 -0
- package/dist/registerUnsafeTools.d.ts.map +1 -0
- package/dist/registerUnsafeTools.js +20 -0
- package/dist/registerUnsafeTools.js.map +1 -0
- package/dist/registerVisualTools.d.ts +12 -0
- package/dist/registerVisualTools.d.ts.map +1 -0
- package/dist/registerVisualTools.js +55 -0
- package/dist/registerVisualTools.js.map +1 -0
- package/dist/stdio.d.ts +3 -0
- package/dist/stdio.d.ts.map +1 -0
- package/dist/stdio.js +30 -0
- package/dist/stdio.js.map +1 -0
- package/dist/toolResult.d.ts +4 -0
- package/dist/toolResult.d.ts.map +1 -0
- package/dist/toolResult.js +13 -0
- package/dist/toolResult.js.map +1 -0
- package/package.json +27 -6
- package/index.js +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registerEditorTools.js","sourceRoot":"","sources":["../src/registerEditorTools.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
import type { ExtensionContext, ExtensionRegistry } from "@godot-mcp/control-plane";
|
|
3
|
+
import { type ToolExecutionDependencies } from "./executeTool.js";
|
|
4
|
+
export interface ExtensionToolDependencies extends ToolExecutionDependencies {
|
|
5
|
+
extensions: ExtensionRegistry;
|
|
6
|
+
extensionContext(correlationId: string): ExtensionContext;
|
|
7
|
+
}
|
|
8
|
+
export declare function registerExtensionTools(server: McpServer, dependencies: ExtensionToolDependencies): void;
|
|
9
|
+
//# sourceMappingURL=registerExtensionTools.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registerExtensionTools.d.ts","sourceRoot":"","sources":["../src/registerExtensionTools.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAGzE,OAAO,KAAK,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAGpF,OAAO,EAAe,KAAK,yBAAyB,EAAE,MAAM,kBAAkB,CAAC;AAe/E,MAAM,WAAW,yBAA0B,SAAQ,yBAAyB;IAC1E,UAAU,EAAE,iBAAiB,CAAC;IAC9B,gBAAgB,CAAC,aAAa,EAAE,MAAM,GAAG,gBAAgB,CAAC;CAC3D;AAED,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,SAAS,EAAE,YAAY,EAAE,yBAAyB,GAAG,IAAI,CAyCvG"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { ToolResultSchema } from "@godot-mcp/protocol";
|
|
3
|
+
import { executeTool } from "./executeTool.js";
|
|
4
|
+
import { toMcpToolResult } from "./toolResult.js";
|
|
5
|
+
const ExtensionCallSchema = z.object({ extension: z.string().regex(/^[a-z][a-z0-9_-]{0,63}$/), operation: z.string().regex(/^[a-z][a-z0-9_-]{0,63}$/), input: z.json() }).strict();
|
|
6
|
+
const RESERVED_AUDIT_KEYS = new Set(["extension", "operation"]);
|
|
7
|
+
function extensionAuditArguments(extension, operation, audit) {
|
|
8
|
+
const facts = audit();
|
|
9
|
+
for (const key of Object.keys(facts))
|
|
10
|
+
if (RESERVED_AUDIT_KEYS.has(key))
|
|
11
|
+
throw new Error(`Extension audit metadata cannot override ${key}`);
|
|
12
|
+
const serializedFacts = JSON.stringify(facts);
|
|
13
|
+
if (serializedFacts === undefined)
|
|
14
|
+
throw new Error("Extension audit metadata must be JSON serializable");
|
|
15
|
+
if (Buffer.byteLength(serializedFacts) > 64 * 1024)
|
|
16
|
+
throw new Error("Extension audit metadata exceeds 64 KiB");
|
|
17
|
+
return { extension, operation, ...facts };
|
|
18
|
+
}
|
|
19
|
+
export function registerExtensionTools(server, dependencies) {
|
|
20
|
+
server.registerTool("godot_extension", {
|
|
21
|
+
title: "Run an allowlisted typed Godot MCP extension",
|
|
22
|
+
description: "Invokes one startup-allowlisted typed extension through normal authorization and audit routing.",
|
|
23
|
+
inputSchema: ExtensionCallSchema,
|
|
24
|
+
outputSchema: ToolResultSchema,
|
|
25
|
+
annotations: { readOnlyHint: false, destructiveHint: true, idempotentHint: false, openWorldHint: true },
|
|
26
|
+
}, async (rawInput) => {
|
|
27
|
+
const input = ExtensionCallSchema.parse(rawInput);
|
|
28
|
+
const serializedInput = JSON.stringify(input.input);
|
|
29
|
+
if (serializedInput === undefined)
|
|
30
|
+
throw new Error("Extension input must be JSON serializable");
|
|
31
|
+
if (Buffer.byteLength(serializedInput) > 256 * 1024)
|
|
32
|
+
throw new Error("Extension input exceeds 256 KiB");
|
|
33
|
+
const definition = dependencies.extensions.resolve(input.extension, input.operation);
|
|
34
|
+
let parsed;
|
|
35
|
+
return toMcpToolResult(await executeTool(dependencies, definition.policy, input, async (correlationId) => {
|
|
36
|
+
const supplied = dependencies.extensionContext(correlationId);
|
|
37
|
+
const context = Object.freeze({
|
|
38
|
+
project: Object.freeze({ ...supplied.project }),
|
|
39
|
+
correlationId,
|
|
40
|
+
evidence: Object.freeze({ putJson: supplied.evidence.putJson.bind(supplied.evidence) }),
|
|
41
|
+
});
|
|
42
|
+
const result = await definition.handler(context, parsed);
|
|
43
|
+
const output = definition.outputSchema.parse(result);
|
|
44
|
+
const serializedOutput = JSON.stringify(output);
|
|
45
|
+
if (serializedOutput === undefined)
|
|
46
|
+
throw new Error("Extension output must be JSON serializable");
|
|
47
|
+
if (Buffer.byteLength(serializedOutput) > 512 * 1024)
|
|
48
|
+
throw new Error("Extension output exceeds 512 KiB");
|
|
49
|
+
return { data: output };
|
|
50
|
+
}, {
|
|
51
|
+
auditArguments: () => {
|
|
52
|
+
parsed = definition.inputSchema.parse(input.input);
|
|
53
|
+
return extensionAuditArguments(input.extension, input.operation, () => definition.audit(parsed));
|
|
54
|
+
},
|
|
55
|
+
auditFallbackArguments: { extension: input.extension, operation: input.operation },
|
|
56
|
+
}));
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
//# sourceMappingURL=registerExtensionTools.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registerExtensionTools.js","sourceRoot":"","sources":["../src/registerExtensionTools.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
import { type InputOperationInput, type InputOperationResult } from "@godot-mcp/protocol";
|
|
3
|
+
import { type ToolExecutionDependencies } from "./executeTool.js";
|
|
4
|
+
export interface InputController {
|
|
5
|
+
input(input: InputOperationInput): Promise<InputOperationResult>;
|
|
6
|
+
}
|
|
7
|
+
export interface InputToolDependencies extends ToolExecutionDependencies {
|
|
8
|
+
runtime: InputController;
|
|
9
|
+
}
|
|
10
|
+
export declare function registerInputTools(server: McpServer, dependencies: InputToolDependencies): void;
|
|
11
|
+
//# sourceMappingURL=registerInputTools.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registerInputTools.d.ts","sourceRoot":"","sources":["../src/registerInputTools.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAMzE,OAAO,EAGL,KAAK,mBAAmB,EACxB,KAAK,oBAAoB,EAC1B,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAAe,KAAK,yBAAyB,EAAE,MAAM,kBAAkB,CAAC;AAG/E,MAAM,WAAW,eAAe;IAC9B,KAAK,CAAC,KAAK,EAAE,mBAAmB,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAAC;CAClE;AAED,MAAM,WAAW,qBAAsB,SAAQ,yBAAyB;IACtE,OAAO,EAAE,eAAe,CAAC;CAC1B;AASD,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,SAAS,EAAE,YAAY,EAAE,qBAAqB,GAAG,IAAI,CAc/F"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { INPUT_POLICY, summarizeInputForAudit, } from "@godot-mcp/control-plane";
|
|
2
|
+
import { InputOperationInputSchema, ToolResultSchema, } from "@godot-mcp/protocol";
|
|
3
|
+
import { executeTool } from "./executeTool.js";
|
|
4
|
+
import { toMcpToolResult } from "./toolResult.js";
|
|
5
|
+
const inputAnnotations = {
|
|
6
|
+
readOnlyHint: false,
|
|
7
|
+
destructiveHint: true,
|
|
8
|
+
idempotentHint: false,
|
|
9
|
+
openWorldHint: false,
|
|
10
|
+
};
|
|
11
|
+
export function registerInputTools(server, dependencies) {
|
|
12
|
+
server.registerTool("godot_input", {
|
|
13
|
+
title: "Automate ephemeral Godot runtime input",
|
|
14
|
+
description: "Inject bounded events, sequences, recordings, and deterministic replays into an authenticated MCP-owned runtime.",
|
|
15
|
+
inputSchema: InputOperationInputSchema,
|
|
16
|
+
outputSchema: ToolResultSchema,
|
|
17
|
+
annotations: inputAnnotations,
|
|
18
|
+
}, async (input) => toMcpToolResult(await executeTool(dependencies, INPUT_POLICY, input, async () => ({ data: await dependencies.runtime.input(input) }), { auditArguments: summarizeInputForAudit(input) })));
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=registerInputTools.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registerInputTools.js","sourceRoot":"","sources":["../src/registerInputTools.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,YAAY,EACZ,sBAAsB,GACvB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EACL,yBAAyB,EACzB,gBAAgB,GAGjB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAAE,WAAW,EAAkC,MAAM,kBAAkB,CAAC;AAC/E,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAUlD,MAAM,gBAAgB,GAAG;IACvB,YAAY,EAAE,KAAK;IACnB,eAAe,EAAE,IAAI;IACrB,cAAc,EAAE,KAAK;IACrB,aAAa,EAAE,KAAK;CACZ,CAAC;AAEX,MAAM,UAAU,kBAAkB,CAAC,MAAiB,EAAE,YAAmC;IACvF,MAAM,CAAC,YAAY,CAAC,aAAa,EAAE;QACjC,KAAK,EAAE,wCAAwC;QAC/C,WAAW,EAAE,kHAAkH;QAC/H,WAAW,EAAE,yBAAyB;QACtC,YAAY,EAAE,gBAAgB;QAC9B,WAAW,EAAE,gBAAgB;KAC9B,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,CAAC,eAAe,CAAC,MAAM,WAAW,CACnD,YAAY,EACZ,YAAY,EACZ,KAAK,EACL,KAAK,IAAI,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC,EAC/D,EAAE,cAAc,EAAE,sBAAsB,CAAC,KAAK,CAAC,EAAE,CAClD,CAAC,CAAC,CAAC;AACN,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
import { type ProjectOperationInput } from "@godot-mcp/protocol";
|
|
3
|
+
import { type ExecutedPayload, type ToolExecutionDependencies } from "./executeTool.js";
|
|
4
|
+
export interface ProjectOperationsController {
|
|
5
|
+
execute(input: ProjectOperationInput, correlationId: string): Promise<ExecutedPayload>;
|
|
6
|
+
}
|
|
7
|
+
export interface ProjectToolDependencies extends ToolExecutionDependencies {
|
|
8
|
+
projectOperations: ProjectOperationsController;
|
|
9
|
+
}
|
|
10
|
+
export declare function registerProjectTools(server: McpServer, dependencies: ProjectToolDependencies): void;
|
|
11
|
+
export declare function projectAuditArguments(input: ProjectOperationInput): Record<string, unknown>;
|
|
12
|
+
//# sourceMappingURL=registerProjectTools.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registerProjectTools.d.ts","sourceRoot":"","sources":["../src/registerProjectTools.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAGzE,OAAO,EAAiD,KAAK,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAEhH,OAAO,EAAe,KAAK,eAAe,EAAE,KAAK,yBAAyB,EAAE,MAAM,kBAAkB,CAAC;AAGrG,MAAM,WAAW,2BAA2B;IAC1C,OAAO,CAAC,KAAK,EAAE,qBAAqB,EAAE,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC,CAAC;CACxF;AAED,MAAM,WAAW,uBAAwB,SAAQ,yBAAyB;IACxE,iBAAiB,EAAE,2BAA2B,CAAC;CAChD;AASD,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,SAAS,EAAE,YAAY,EAAE,uBAAuB,GAAG,IAAI,CAcnG;AAMD,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,qBAAqB,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CA4B3F"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { PROJECT_POLICY } from "@godot-mcp/control-plane";
|
|
3
|
+
import { ProjectOperationInputSchema, ToolResultSchema } from "@godot-mcp/protocol";
|
|
4
|
+
import { executeTool } from "./executeTool.js";
|
|
5
|
+
import { toMcpToolResult } from "./toolResult.js";
|
|
6
|
+
const annotations = {
|
|
7
|
+
readOnlyHint: false,
|
|
8
|
+
destructiveHint: true,
|
|
9
|
+
idempotentHint: false,
|
|
10
|
+
openWorldHint: false,
|
|
11
|
+
};
|
|
12
|
+
export function registerProjectTools(server, dependencies) {
|
|
13
|
+
server.registerTool("godot_project", {
|
|
14
|
+
title: "Operate one authorized Godot project",
|
|
15
|
+
description: "Apply bounded project settings or manage cancellable import, run, build, and export jobs with scanned artifacts.",
|
|
16
|
+
inputSchema: ProjectOperationInputSchema,
|
|
17
|
+
outputSchema: ToolResultSchema,
|
|
18
|
+
annotations,
|
|
19
|
+
}, async (input) => toMcpToolResult(await executeTool(dependencies, PROJECT_POLICY, input, async (correlationId) => dependencies.projectOperations.execute(input, correlationId), { auditArguments: projectAuditArguments(input) })));
|
|
20
|
+
}
|
|
21
|
+
function digest(value) {
|
|
22
|
+
return createHash("sha256").update(value).digest("hex");
|
|
23
|
+
}
|
|
24
|
+
export function projectAuditArguments(input) {
|
|
25
|
+
if (input.operation === "settings_apply") {
|
|
26
|
+
return {
|
|
27
|
+
operation: input.operation,
|
|
28
|
+
settingCount: input.changes.length,
|
|
29
|
+
settingNameSha256: input.changes.map((change) => digest(change.name)).sort(),
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
if (input.operation === "plugin_set") {
|
|
33
|
+
return { operation: input.operation, pluginSha256: digest(input.pluginPath), enabled: input.enabled };
|
|
34
|
+
}
|
|
35
|
+
if (input.operation === "import_start") {
|
|
36
|
+
return { operation: input.operation, kind: input.kind, resourceCount: input.resourcePaths?.length ?? 0, deadlineMs: input.deadlineMs };
|
|
37
|
+
}
|
|
38
|
+
if (input.operation === "run_start") {
|
|
39
|
+
return { operation: input.operation, hasScene: input.scenePath !== undefined, headless: input.headless, deadlineMs: input.deadlineMs };
|
|
40
|
+
}
|
|
41
|
+
if (input.operation === "build_start")
|
|
42
|
+
return { operation: input.operation, kind: input.kind, deadlineMs: input.deadlineMs };
|
|
43
|
+
if (input.operation === "export_start") {
|
|
44
|
+
return {
|
|
45
|
+
operation: input.operation,
|
|
46
|
+
presetSha256: digest(input.preset),
|
|
47
|
+
artifactNameSha256: digest(input.artifactName),
|
|
48
|
+
mode: input.mode,
|
|
49
|
+
deadlineMs: input.deadlineMs,
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
return { operation: input.operation };
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=registerProjectTools.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registerProjectTools.js","sourceRoot":"","sources":["../src/registerProjectTools.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
import { type EvidenceStore } from "@godot-mcp/control-plane";
|
|
3
|
+
import { type RuntimeCaptureInput, type RuntimeLaunchPins, type RuntimeOperationInput } from "@godot-mcp/protocol";
|
|
4
|
+
import { type ToolExecutionDependencies } from "./executeTool.js";
|
|
5
|
+
export interface RuntimeFrame {
|
|
6
|
+
data: Uint8Array;
|
|
7
|
+
metadata: {
|
|
8
|
+
mimeType: "image/png";
|
|
9
|
+
width: number;
|
|
10
|
+
height: number;
|
|
11
|
+
byteLength: number;
|
|
12
|
+
sha256: string;
|
|
13
|
+
frameIndex: number;
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
export interface RuntimeController {
|
|
17
|
+
launch(input: {
|
|
18
|
+
scenePath: string;
|
|
19
|
+
startupTimeoutMs: number;
|
|
20
|
+
pins?: RuntimeLaunchPins;
|
|
21
|
+
}): Promise<unknown>;
|
|
22
|
+
execute(input: Exclude<RuntimeOperationInput, {
|
|
23
|
+
operation: "launch";
|
|
24
|
+
}>): Promise<unknown>;
|
|
25
|
+
capture(input: RuntimeCaptureInput): Promise<{
|
|
26
|
+
frames: RuntimeFrame[];
|
|
27
|
+
}>;
|
|
28
|
+
}
|
|
29
|
+
export interface RuntimeToolDependencies extends ToolExecutionDependencies {
|
|
30
|
+
evidence: EvidenceStore;
|
|
31
|
+
runtime: RuntimeController;
|
|
32
|
+
}
|
|
33
|
+
export declare function registerRuntimeTools(server: McpServer, dependencies: RuntimeToolDependencies): void;
|
|
34
|
+
//# sourceMappingURL=registerRuntimeTools.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registerRuntimeTools.d.ts","sourceRoot":"","sources":["../src/registerRuntimeTools.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEzE,OAAO,EAGL,KAAK,aAAa,EACnB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAKL,KAAK,mBAAmB,EACxB,KAAK,iBAAiB,EACtB,KAAK,qBAAqB,EAC3B,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAAe,KAAK,yBAAyB,EAAE,MAAM,kBAAkB,CAAC;AAG/E,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,UAAU,CAAC;IACjB,QAAQ,EAAE;QACR,QAAQ,EAAE,WAAW,CAAC;QACtB,KAAK,EAAE,MAAM,CAAC;QACd,MAAM,EAAE,MAAM,CAAC;QACf,UAAU,EAAE,MAAM,CAAC;QACnB,MAAM,EAAE,MAAM,CAAC;QACf,UAAU,EAAE,MAAM,CAAC;KACpB,CAAC;CACH;AAED,MAAM,WAAW,iBAAiB;IAChC,MAAM,CAAC,KAAK,EAAE;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,gBAAgB,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,iBAAiB,CAAA;KAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC3G,OAAO,CAAC,KAAK,EAAE,OAAO,CAAC,qBAAqB,EAAE;QAAE,SAAS,EAAE,QAAQ,CAAA;KAAE,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC1F,OAAO,CAAC,KAAK,EAAE,mBAAmB,GAAG,OAAO,CAAC;QAAE,MAAM,EAAE,YAAY,EAAE,CAAA;KAAE,CAAC,CAAC;CAC1E;AAED,MAAM,WAAW,uBAAwB,SAAQ,yBAAyB;IACxE,QAAQ,EAAE,aAAa,CAAC;IACxB,OAAO,EAAE,iBAAiB,CAAC;CAC5B;AAgBD,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,SAAS,EAAE,YAAY,EAAE,uBAAuB,GAAG,IAAI,CA8DnG"}
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { RUNTIME_CAPTURE_POLICY, RUNTIME_POLICY, } from "@godot-mcp/control-plane";
|
|
3
|
+
import { RuntimeCaptureFrameMetadataSchema, RuntimeCaptureInputSchema, RuntimeOperationInputSchema, ToolResultSchema, } from "@godot-mcp/protocol";
|
|
4
|
+
import { executeTool } from "./executeTool.js";
|
|
5
|
+
import { toMcpToolResult } from "./toolResult.js";
|
|
6
|
+
const runtimeAnnotations = {
|
|
7
|
+
readOnlyHint: false,
|
|
8
|
+
destructiveHint: true,
|
|
9
|
+
idempotentHint: false,
|
|
10
|
+
openWorldHint: false,
|
|
11
|
+
};
|
|
12
|
+
const captureAnnotations = {
|
|
13
|
+
readOnlyHint: false,
|
|
14
|
+
destructiveHint: false,
|
|
15
|
+
idempotentHint: false,
|
|
16
|
+
openWorldHint: false,
|
|
17
|
+
};
|
|
18
|
+
export function registerRuntimeTools(server, dependencies) {
|
|
19
|
+
server.registerTool("godot_runtime", {
|
|
20
|
+
title: "Control ephemeral Godot runtime",
|
|
21
|
+
description: "Launch, inspect, debug, profile, control, or stop one authenticated MCP-owned runtime.",
|
|
22
|
+
inputSchema: RuntimeOperationInputSchema,
|
|
23
|
+
outputSchema: ToolResultSchema,
|
|
24
|
+
annotations: runtimeAnnotations,
|
|
25
|
+
}, async (input) => {
|
|
26
|
+
const auditArguments = runtimeAuditArguments(input);
|
|
27
|
+
return toMcpToolResult(await executeTool(dependencies, RUNTIME_POLICY, input, async () => {
|
|
28
|
+
if (input.operation === "launch") {
|
|
29
|
+
return { data: await dependencies.runtime.launch({
|
|
30
|
+
scenePath: input.scenePath,
|
|
31
|
+
startupTimeoutMs: input.startupTimeoutMs,
|
|
32
|
+
...(input.pins ? { pins: input.pins } : {}),
|
|
33
|
+
}) };
|
|
34
|
+
}
|
|
35
|
+
const data = await dependencies.runtime.execute(input);
|
|
36
|
+
const audit = performanceAuditFacts(input, data);
|
|
37
|
+
return { data, ...(audit === undefined ? {} : { audit }) };
|
|
38
|
+
}, { auditArguments }));
|
|
39
|
+
});
|
|
40
|
+
server.registerTool("godot_runtime_capture", {
|
|
41
|
+
title: "Capture ephemeral Godot runtime",
|
|
42
|
+
description: "Return one to eight bounded PNG frames from the authenticated MCP-owned runtime.",
|
|
43
|
+
inputSchema: RuntimeCaptureInputSchema,
|
|
44
|
+
outputSchema: ToolResultSchema,
|
|
45
|
+
annotations: captureAnnotations,
|
|
46
|
+
}, async (input) => toMcpToolResult(await executeTool(dependencies, RUNTIME_CAPTURE_POLICY, input, async () => {
|
|
47
|
+
const captured = await dependencies.runtime.capture(input);
|
|
48
|
+
if (captured.frames.length !== input.frameCount)
|
|
49
|
+
throw new Error("Runtime capture returned an unexpected frame count");
|
|
50
|
+
const attachment = dependencies.session.snapshot().attachment;
|
|
51
|
+
if (!attachment)
|
|
52
|
+
throw new Error("Godot editor addon is not attached");
|
|
53
|
+
const evidence = [];
|
|
54
|
+
const frames = [];
|
|
55
|
+
const images = [];
|
|
56
|
+
for (const [frameIndex, frame] of captured.frames.entries()) {
|
|
57
|
+
const metadata = RuntimeCaptureFrameMetadataSchema.parse(frame.metadata);
|
|
58
|
+
const digest = createHash("sha256").update(frame.data).digest("hex");
|
|
59
|
+
if (metadata.frameIndex !== frameIndex ||
|
|
60
|
+
metadata.byteLength !== frame.data.byteLength ||
|
|
61
|
+
metadata.sha256 !== digest ||
|
|
62
|
+
metadata.width > input.maxWidth ||
|
|
63
|
+
metadata.height > input.maxHeight)
|
|
64
|
+
throw new Error("Runtime capture metadata does not match verified PNG bytes or request bounds");
|
|
65
|
+
const stored = await dependencies.evidence.putPng(attachment.sessionId, frame.data, {
|
|
66
|
+
source: "runtime",
|
|
67
|
+
viewport: "runtime",
|
|
68
|
+
width: metadata.width,
|
|
69
|
+
height: metadata.height,
|
|
70
|
+
runId: input.handle.runId,
|
|
71
|
+
generation: input.handle.generation,
|
|
72
|
+
frameIndex,
|
|
73
|
+
});
|
|
74
|
+
evidence.push(stored.observationUri);
|
|
75
|
+
frames.push({ ...metadata, evidenceUri: stored.uri, evidenceObservationUri: stored.observationUri });
|
|
76
|
+
images.push({ data: frame.data, mimeType: "image/png" });
|
|
77
|
+
}
|
|
78
|
+
return { data: { handle: input.handle, frames }, evidence, images };
|
|
79
|
+
})));
|
|
80
|
+
}
|
|
81
|
+
function runtimeAuditArguments(input) {
|
|
82
|
+
if (input.operation === "monitor_snapshot")
|
|
83
|
+
return { operation: input.operation, groupCount: input.groups.length };
|
|
84
|
+
if (input.operation === "profile_start") {
|
|
85
|
+
return {
|
|
86
|
+
operation: input.operation,
|
|
87
|
+
durationMs: input.durationMs,
|
|
88
|
+
intervalFrames: input.intervalFrames,
|
|
89
|
+
groupCount: input.groups.length,
|
|
90
|
+
retainRaw: input.retainRaw,
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
if (input.operation === "profile_status" || input.operation === "profile_cancel" || input.operation === "profile_result") {
|
|
94
|
+
return { operation: input.operation };
|
|
95
|
+
}
|
|
96
|
+
if (input.operation === "debug_breakpoints_set") {
|
|
97
|
+
return {
|
|
98
|
+
operation: input.operation,
|
|
99
|
+
breakpointCount: input.breakpoints.length,
|
|
100
|
+
sourceCount: new Set(input.breakpoints.map((entry) => entry.sourcePath)).size,
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
if (input.operation === "debug_watch") {
|
|
104
|
+
return {
|
|
105
|
+
operation: input.operation,
|
|
106
|
+
selectorCount: input.selectors.length,
|
|
107
|
+
maxDepth: Math.max(...input.selectors.map((selector) => selector.path.length)),
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
if (input.operation === "debug_stack")
|
|
111
|
+
return { operation: input.operation, offset: input.offset, limit: input.limit };
|
|
112
|
+
if (input.operation === "debug_variables")
|
|
113
|
+
return { operation: input.operation, scope: input.scope, offset: input.offset, limit: input.limit };
|
|
114
|
+
if (input.operation === "debug_children")
|
|
115
|
+
return { operation: input.operation, offset: input.offset, limit: input.limit };
|
|
116
|
+
if (input.operation === "debug_wait")
|
|
117
|
+
return { operation: input.operation, afterSequence: input.afterSequence, timeoutMs: input.timeoutMs };
|
|
118
|
+
if (input.operation.startsWith("debug_"))
|
|
119
|
+
return { operation: input.operation };
|
|
120
|
+
return input;
|
|
121
|
+
}
|
|
122
|
+
function performanceAuditFacts(input, data) {
|
|
123
|
+
if (input.operation !== "monitor_snapshot" && !input.operation.startsWith("profile_"))
|
|
124
|
+
return undefined;
|
|
125
|
+
const record = isRecord(data) ? data : {};
|
|
126
|
+
const evidence = isRecord(record.evidence) ? record.evidence : {};
|
|
127
|
+
const metadata = {
|
|
128
|
+
kind: "runtime_performance",
|
|
129
|
+
operation: input.operation,
|
|
130
|
+
...(typeof record.state === "string" ? { state: record.state } : {}),
|
|
131
|
+
...(typeof record.observedSamples === "number" ? { observedSamples: record.observedSamples } : {}),
|
|
132
|
+
...(typeof record.retainedSamples === "number" ? { retainedSamples: record.retainedSamples } : {}),
|
|
133
|
+
...(typeof evidence.sha256 === "string" ? { sha256: evidence.sha256 } : {}),
|
|
134
|
+
...(input.operation === "monitor_snapshot" && isRecord(record.groups) ? { groupCount: Object.keys(record.groups).length } : {}),
|
|
135
|
+
};
|
|
136
|
+
return {
|
|
137
|
+
targetIdentities: [metadata],
|
|
138
|
+
preconditions: [],
|
|
139
|
+
idempotencyKeySha256: null,
|
|
140
|
+
partialEffects: false,
|
|
141
|
+
rollback: "not_needed",
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
function isRecord(value) {
|
|
145
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
146
|
+
}
|
|
147
|
+
//# sourceMappingURL=registerRuntimeTools.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registerRuntimeTools.js","sourceRoot":"","sources":["../src/registerRuntimeTools.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
import { type UnsafeFixtureOperationInput } from "@godot-mcp/protocol";
|
|
3
|
+
import { type ExecutedPayload, type ToolExecutionDependencies } from "./executeTool.js";
|
|
4
|
+
export interface UnsafeFixtureController {
|
|
5
|
+
execute(input: UnsafeFixtureOperationInput, correlationId: string): Promise<ExecutedPayload>;
|
|
6
|
+
}
|
|
7
|
+
export interface UnsafeToolDependencies extends ToolExecutionDependencies {
|
|
8
|
+
unsafeFixture: UnsafeFixtureController;
|
|
9
|
+
}
|
|
10
|
+
export declare function registerUnsafeTools(server: McpServer, dependencies: UnsafeToolDependencies): void;
|
|
11
|
+
export declare function unsafeAuditArguments(input: UnsafeFixtureOperationInput): Record<string, unknown>;
|
|
12
|
+
//# sourceMappingURL=registerUnsafeTools.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registerUnsafeTools.d.ts","sourceRoot":"","sources":["../src/registerUnsafeTools.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAGzE,OAAO,EAAuD,KAAK,2BAA2B,EAAE,MAAM,qBAAqB,CAAC;AAE5H,OAAO,EAAe,KAAK,eAAe,EAAE,KAAK,yBAAyB,EAAE,MAAM,kBAAkB,CAAC;AAGrG,MAAM,WAAW,uBAAuB;IACtC,OAAO,CAAC,KAAK,EAAE,2BAA2B,EAAE,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC,CAAC;CAC9F;AAED,MAAM,WAAW,sBAAuB,SAAQ,yBAAyB;IAAG,aAAa,EAAE,uBAAuB,CAAA;CAAE;AAEpH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,SAAS,EAAE,YAAY,EAAE,sBAAsB,GAAG,IAAI,CAcjG;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,2BAA2B,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAIhG"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { UNSAFE_POLICY } from "@godot-mcp/control-plane";
|
|
3
|
+
import { ToolResultSchema, UnsafeFixtureOperationInputSchema } from "@godot-mcp/protocol";
|
|
4
|
+
import { executeTool } from "./executeTool.js";
|
|
5
|
+
import { toMcpToolResult } from "./toolResult.js";
|
|
6
|
+
export function registerUnsafeTools(server, dependencies) {
|
|
7
|
+
server.registerTool("godot_unsafe_fixture", {
|
|
8
|
+
title: "UNSAFE: execute unsandboxed code in a registered disposable fixture",
|
|
9
|
+
description: "Runs arbitrary GDScript as your OS user in a separately registered disposable fixture. This is not a sandbox.",
|
|
10
|
+
inputSchema: UnsafeFixtureOperationInputSchema,
|
|
11
|
+
outputSchema: ToolResultSchema,
|
|
12
|
+
annotations: { readOnlyHint: false, destructiveHint: true, idempotentHint: false, openWorldHint: true },
|
|
13
|
+
}, async (input) => toMcpToolResult(await executeTool(dependencies, UNSAFE_POLICY, input, (correlationId) => dependencies.unsafeFixture.execute(input, correlationId), { auditArguments: unsafeAuditArguments(input) })));
|
|
14
|
+
}
|
|
15
|
+
export function unsafeAuditArguments(input) {
|
|
16
|
+
return input.operation === "execute_start"
|
|
17
|
+
? { operation: input.operation, sourceSha256: createHash("sha256").update(input.source).digest("hex"), sourceBytes: Buffer.byteLength(input.source), deadlineMs: input.deadlineMs, unsafe: true, sandboxed: false }
|
|
18
|
+
: { operation: input.operation, unsafe: true, sandboxed: false };
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=registerUnsafeTools.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registerUnsafeTools.js","sourceRoot":"","sources":["../src/registerUnsafeTools.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAIzC,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AACzD,OAAO,EAAE,gBAAgB,EAAE,iCAAiC,EAAoC,MAAM,qBAAqB,CAAC;AAE5H,OAAO,EAAE,WAAW,EAAwD,MAAM,kBAAkB,CAAC;AACrG,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAQlD,MAAM,UAAU,mBAAmB,CAAC,MAAiB,EAAE,YAAoC;IACzF,MAAM,CAAC,YAAY,CAAC,sBAAsB,EAAE;QAC1C,KAAK,EAAE,qEAAqE;QAC5E,WAAW,EAAE,+GAA+G;QAC5H,WAAW,EAAE,iCAAiC;QAC9C,YAAY,EAAE,gBAAgB;QAC9B,WAAW,EAAE,EAAE,YAAY,EAAE,KAAK,EAAE,eAAe,EAAE,IAAI,EAAE,cAAc,EAAE,KAAK,EAAE,aAAa,EAAE,IAAI,EAAE;KACxG,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,CAAC,eAAe,CAAC,MAAM,WAAW,CACnD,YAAY,EACZ,aAAa,EACb,KAAK,EACL,CAAC,aAAa,EAAE,EAAE,CAAC,YAAY,CAAC,aAAa,CAAC,OAAO,CAAC,KAAK,EAAE,aAAa,CAAC,EAC3E,EAAE,cAAc,EAAE,oBAAoB,CAAC,KAAK,CAAC,EAAE,CAChD,CAAC,CAAC,CAAC;AACN,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,KAAkC;IACrE,OAAO,KAAK,CAAC,SAAS,KAAK,eAAe;QACxC,CAAC,CAAC,EAAE,SAAS,EAAE,KAAK,CAAC,SAAS,EAAE,YAAY,EAAE,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,WAAW,EAAE,MAAM,CAAC,UAAU,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,UAAU,EAAE,KAAK,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE;QACnN,CAAC,CAAC,EAAE,SAAS,EAAE,KAAK,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC;AACrE,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
import { type VisualOperationInput } from "@godot-mcp/protocol";
|
|
3
|
+
import { type ExecutedPayload, type ToolExecutionDependencies } from "./executeTool.js";
|
|
4
|
+
export interface VisualController {
|
|
5
|
+
execute(input: VisualOperationInput): Promise<ExecutedPayload>;
|
|
6
|
+
}
|
|
7
|
+
export interface VisualToolDependencies extends ToolExecutionDependencies {
|
|
8
|
+
visual: VisualController;
|
|
9
|
+
}
|
|
10
|
+
export declare function registerVisualTools(server: McpServer, dependencies: VisualToolDependencies): void;
|
|
11
|
+
export declare function visualAuditArguments(input: VisualOperationInput): Record<string, unknown>;
|
|
12
|
+
//# sourceMappingURL=registerVisualTools.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registerVisualTools.d.ts","sourceRoot":"","sources":["../src/registerVisualTools.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAGzE,OAAO,EAGL,KAAK,oBAAoB,EAC1B,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAAe,KAAK,eAAe,EAAE,KAAK,yBAAyB,EAAE,MAAM,kBAAkB,CAAC;AAGrG,MAAM,WAAW,gBAAgB;IAC/B,OAAO,CAAC,KAAK,EAAE,oBAAoB,GAAG,OAAO,CAAC,eAAe,CAAC,CAAC;CAChE;AAED,MAAM,WAAW,sBAAuB,SAAQ,yBAAyB;IACvE,MAAM,EAAE,gBAAgB,CAAC;CAC1B;AASD,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,SAAS,EAAE,YAAY,EAAE,sBAAsB,GAAG,IAAI,CAcjG;AAMD,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,oBAAoB,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CA4BzF"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { VISUAL_POLICY } from "@godot-mcp/control-plane";
|
|
3
|
+
import { ToolResultSchema, VisualOperationInputSchema, } from "@godot-mcp/protocol";
|
|
4
|
+
import { executeTool } from "./executeTool.js";
|
|
5
|
+
import { toMcpToolResult } from "./toolResult.js";
|
|
6
|
+
const visualAnnotations = {
|
|
7
|
+
readOnlyHint: false,
|
|
8
|
+
destructiveHint: true,
|
|
9
|
+
idempotentHint: false,
|
|
10
|
+
openWorldHint: false,
|
|
11
|
+
};
|
|
12
|
+
export function registerVisualTools(server, dependencies) {
|
|
13
|
+
server.registerTool("godot_visual", {
|
|
14
|
+
title: "Run bounded Godot visual QA",
|
|
15
|
+
description: "Manage immutable PNG baselines, deterministic comparisons, and cancellable authenticated playtest scenarios.",
|
|
16
|
+
inputSchema: VisualOperationInputSchema,
|
|
17
|
+
outputSchema: ToolResultSchema,
|
|
18
|
+
annotations: visualAnnotations,
|
|
19
|
+
}, async (input) => toMcpToolResult(await executeTool(dependencies, VISUAL_POLICY, input, async () => dependencies.visual.execute(input), { auditArguments: visualAuditArguments(input) })));
|
|
20
|
+
}
|
|
21
|
+
function sha256(value) {
|
|
22
|
+
return createHash("sha256").update(value).digest("hex");
|
|
23
|
+
}
|
|
24
|
+
export function visualAuditArguments(input) {
|
|
25
|
+
if (input.operation === "scenario_start") {
|
|
26
|
+
const stepKinds = {};
|
|
27
|
+
for (const step of input.scenario.steps)
|
|
28
|
+
stepKinds[step.kind] = (stepKinds[step.kind] ?? 0) + 1;
|
|
29
|
+
return {
|
|
30
|
+
operation: input.operation,
|
|
31
|
+
scenarioNameSha256: sha256(input.scenario.name),
|
|
32
|
+
stepCount: input.scenario.steps.length,
|
|
33
|
+
stepKinds,
|
|
34
|
+
deadlineMs: input.scenario.deadlineMs,
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
if (input.operation === "baseline_create" || input.operation === "compare") {
|
|
38
|
+
const observationSha256 = input.observationUri.split("/")[3];
|
|
39
|
+
return {
|
|
40
|
+
operation: input.operation,
|
|
41
|
+
baselineNameSha256: sha256(input.name),
|
|
42
|
+
...(observationSha256 ? { observationSha256 } : {}),
|
|
43
|
+
...(input.operation === "compare" ? {
|
|
44
|
+
maskCount: input.settings.masks.length,
|
|
45
|
+
maxChannelDelta: input.settings.maxChannelDelta,
|
|
46
|
+
maxDifferentPixels: input.settings.maxDifferentPixels,
|
|
47
|
+
maxDifferentRatioMillionths: input.settings.maxDifferentRatioMillionths,
|
|
48
|
+
} : {}),
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
if (input.operation === "baseline_get")
|
|
52
|
+
return { operation: input.operation, baselineNameSha256: sha256(input.name) };
|
|
53
|
+
return { operation: input.operation };
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=registerVisualTools.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registerVisualTools.js","sourceRoot":"","sources":["../src/registerVisualTools.ts"],"names":[],"mappings":"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"}
|
package/dist/stdio.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stdio.d.ts","sourceRoot":"","sources":["../src/stdio.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAGzE,wBAAsB,YAAY,CAChC,MAAM,EAAE,SAAS,EACjB,OAAO,GAAE,MAAM,OAAO,CAAC,IAAI,CAAyB,GACnD,OAAO,CAAC,IAAI,CAAC,CA0Bf"}
|
package/dist/stdio.js
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
2
|
+
export async function connectStdio(server, cleanup = async () => undefined) {
|
|
3
|
+
const transport = new StdioServerTransport();
|
|
4
|
+
let closePromise;
|
|
5
|
+
const close = () => {
|
|
6
|
+
closePromise ??= (async () => {
|
|
7
|
+
await transport.close().catch(() => undefined);
|
|
8
|
+
await server.close().catch(() => undefined);
|
|
9
|
+
await cleanup();
|
|
10
|
+
})();
|
|
11
|
+
return closePromise;
|
|
12
|
+
};
|
|
13
|
+
const signalHandler = () => {
|
|
14
|
+
void close().then(() => {
|
|
15
|
+
process.exitCode = 0;
|
|
16
|
+
});
|
|
17
|
+
};
|
|
18
|
+
process.once("SIGINT", signalHandler);
|
|
19
|
+
process.once("SIGTERM", signalHandler);
|
|
20
|
+
try {
|
|
21
|
+
await server.connect(transport);
|
|
22
|
+
}
|
|
23
|
+
catch (error) {
|
|
24
|
+
process.stderr.write(`${error instanceof Error ? error.message : String(error)}\n`);
|
|
25
|
+
process.exitCode = 1;
|
|
26
|
+
await close();
|
|
27
|
+
throw error;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=stdio.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stdio.js","sourceRoot":"","sources":["../src/stdio.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AAEjF,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,MAAiB,EACjB,UAA+B,KAAK,IAAI,EAAE,CAAC,SAAS;IAEpD,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;IAC7C,IAAI,YAAuC,CAAC;IAC5C,MAAM,KAAK,GAAG,GAAkB,EAAE;QAChC,YAAY,KAAK,CAAC,KAAK,IAAI,EAAE;YAC3B,MAAM,SAAS,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;YAC/C,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;YAC5C,MAAM,OAAO,EAAE,CAAC;QAClB,CAAC,CAAC,EAAE,CAAC;QACL,OAAO,YAAY,CAAC;IACtB,CAAC,CAAC;IACF,MAAM,aAAa,GAAG,GAAS,EAAE;QAC/B,KAAK,KAAK,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE;YACrB,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;QACvB,CAAC,CAAC,CAAC;IACL,CAAC,CAAC;IACF,OAAO,CAAC,IAAI,CAAC,QAAQ,EAAE,aAAa,CAAC,CAAC;IACtC,OAAO,CAAC,IAAI,CAAC,SAAS,EAAE,aAAa,CAAC,CAAC;IACvC,IAAI,CAAC;QACH,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAClC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACpF,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;QACrB,MAAM,KAAK,EAAE,CAAC;QACd,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"toolResult.d.ts","sourceRoot":"","sources":["../src/toolResult.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AAEzE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAE3D,wBAAgB,eAAe,CAAC,QAAQ,EAAE,kBAAkB,GAAG,cAAc,CAW5E"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export function toMcpToolResult(executed) {
|
|
2
|
+
const { result, image, images } = executed;
|
|
3
|
+
const imageContent = images ?? (image ? [image] : []);
|
|
4
|
+
return {
|
|
5
|
+
content: [
|
|
6
|
+
{ type: "text", text: JSON.stringify(result) },
|
|
7
|
+
...imageContent.map((item) => ({ type: "image", data: Buffer.from(item.data).toString("base64"), mimeType: item.mimeType })),
|
|
8
|
+
],
|
|
9
|
+
structuredContent: result,
|
|
10
|
+
isError: !result.ok,
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=toolResult.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"toolResult.js","sourceRoot":"","sources":["../src/toolResult.ts"],"names":[],"mappings":"AAIA,MAAM,UAAU,eAAe,CAAC,QAA4B;IAC1D,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,QAAQ,CAAC;IAC3C,MAAM,YAAY,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IACtD,OAAO;QACL,OAAO,EAAE;YACP,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE;YAC9C,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,OAAgB,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC;SACtI;QACD,iBAAiB,EAAE,MAA4C;QAC/D,OAAO,EAAE,CAAC,MAAM,CAAC,EAAE;KACpB,CAAC;AACJ,CAAC"}
|