@openfairygui/mcp 0.5.0-alpha.2 → 0.5.0-alpha.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/dist/index.cjs +1 -1
- package/dist/index.mjs +1 -1
- package/dist/{stdio-D33c37mD.cjs → stdio-BRrNOeUP.cjs} +20 -13
- package/dist/{stdio--4YykL4s.mjs → stdio-t-TXHfJJ.mjs} +20 -13
- package/dist/stdio.cjs +1 -1
- package/dist/stdio.mjs +1 -1
- package/package.json +4 -4
- package/src/tool-definitions.ts +14 -8
- package/src/tool-handler.ts +5 -4
package/dist/index.cjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
const require_stdio = require("./stdio-
|
|
2
|
+
const require_stdio = require("./stdio-BRrNOeUP.cjs");
|
|
3
3
|
let _openfairygui_backend_docs = require("@openfairygui/backend/docs");
|
|
4
4
|
exports.OPENFAIRYGUI_BACKEND_CAPABILITIES_RESOURCE_URI = require_stdio.OPENFAIRYGUI_BACKEND_CAPABILITIES_RESOURCE_URI;
|
|
5
5
|
exports.OPENFAIRYGUI_BACKEND_PROMPT_DEFINITIONS = require_stdio.OPENFAIRYGUI_BACKEND_PROMPT_DEFINITIONS;
|
package/dist/index.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as OPENFAIRYGUI_BACKEND_TOOL_NAMES, c as OPENFAIRYGUI_BACKEND_RESOURCE_TEMPLATES, d as getOpenFairyGuiOperationCatalog, f as getOpenFairyGuiOperationSchema, i as OPENFAIRYGUI_BACKEND_TOOL_DEFINITIONS, l as OPENFAIRYGUI_OPERATION_CATALOG_URI, m as OPENFAIRYGUI_BACKEND_PROMPT_NAMES, n as createOpenFairyGuiMcpServer, o as OPENFAIRYGUI_BACKEND_TOOL_PREFIX, p as OPENFAIRYGUI_BACKEND_PROMPT_DEFINITIONS, r as callOpenFairyGuiBackendTool, s as OPENFAIRYGUI_BACKEND_CAPABILITIES_RESOURCE_URI, t as connectOpenFairyGuiMcpStdio, u as OPENFAIRYGUI_OPERATION_SCHEMA_TEMPLATE } from "./stdio
|
|
1
|
+
import { a as OPENFAIRYGUI_BACKEND_TOOL_NAMES, c as OPENFAIRYGUI_BACKEND_RESOURCE_TEMPLATES, d as getOpenFairyGuiOperationCatalog, f as getOpenFairyGuiOperationSchema, i as OPENFAIRYGUI_BACKEND_TOOL_DEFINITIONS, l as OPENFAIRYGUI_OPERATION_CATALOG_URI, m as OPENFAIRYGUI_BACKEND_PROMPT_NAMES, n as createOpenFairyGuiMcpServer, o as OPENFAIRYGUI_BACKEND_TOOL_PREFIX, p as OPENFAIRYGUI_BACKEND_PROMPT_DEFINITIONS, r as callOpenFairyGuiBackendTool, s as OPENFAIRYGUI_BACKEND_CAPABILITIES_RESOURCE_URI, t as connectOpenFairyGuiMcpStdio, u as OPENFAIRYGUI_OPERATION_SCHEMA_TEMPLATE } from "./stdio-t-TXHfJJ.mjs";
|
|
2
2
|
export { OPENFAIRYGUI_BACKEND_CAPABILITIES_RESOURCE_URI, OPENFAIRYGUI_BACKEND_PROMPT_DEFINITIONS, OPENFAIRYGUI_BACKEND_PROMPT_NAMES, OPENFAIRYGUI_BACKEND_RESOURCE_TEMPLATES, OPENFAIRYGUI_BACKEND_TOOL_DEFINITIONS, OPENFAIRYGUI_BACKEND_TOOL_NAMES, OPENFAIRYGUI_BACKEND_TOOL_PREFIX, OPENFAIRYGUI_OPERATION_CATALOG_URI, OPENFAIRYGUI_OPERATION_SCHEMA_TEMPLATE, callOpenFairyGuiBackendTool, connectOpenFairyGuiMcpStdio, createOpenFairyGuiMcpServer, getOpenFairyGuiOperationCatalog, getOpenFairyGuiOperationSchema };
|
|
@@ -501,16 +501,16 @@ const OPENFAIRYGUI_BACKEND_TOOL_METADATA = [
|
|
|
501
501
|
//#region src/tool-definitions.ts
|
|
502
502
|
const OPENFAIRYGUI_BACKEND_TOOL_PREFIX = "openfairygui_backend_";
|
|
503
503
|
const OPENFAIRYGUI_BACKEND_TOOL_NAMES = OPENFAIRYGUI_BACKEND_TOOL_METADATA.map((entry) => entry.name);
|
|
504
|
-
function isOpenFairyGuiMcpPayloadWithinBudget(root) {
|
|
504
|
+
function isOpenFairyGuiMcpPayloadWithinBudget(root, bytePaths = []) {
|
|
505
505
|
const pending = [{
|
|
506
506
|
value: root,
|
|
507
|
-
|
|
507
|
+
path: []
|
|
508
508
|
}];
|
|
509
|
-
let nodes = 0;
|
|
509
|
+
let nodes = 0, binaryBytes = 0;
|
|
510
510
|
while (pending.length > 0) {
|
|
511
|
-
const { value,
|
|
511
|
+
const { value, path } = pending.pop();
|
|
512
512
|
nodes += 1;
|
|
513
|
-
if (nodes > 1e5 ||
|
|
513
|
+
if (nodes > 1e5 || path.length > 32) return false;
|
|
514
514
|
if (value === null || typeof value === "boolean") continue;
|
|
515
515
|
if (typeof value === "number") {
|
|
516
516
|
if (!Number.isFinite(value)) return false;
|
|
@@ -521,23 +521,29 @@ function isOpenFairyGuiMcpPayloadWithinBudget(root) {
|
|
|
521
521
|
continue;
|
|
522
522
|
}
|
|
523
523
|
if (value instanceof Uint8Array) {
|
|
524
|
-
|
|
524
|
+
binaryBytes += value.byteLength;
|
|
525
|
+
if (binaryBytes > 8 * 1024 * 1024) return false;
|
|
525
526
|
continue;
|
|
526
527
|
}
|
|
527
528
|
if (Array.isArray(value)) {
|
|
529
|
+
if (bytePaths.some((parts) => parts.length === path.length && parts.every((part, index) => part === "*" || part === path[index]))) {
|
|
530
|
+
binaryBytes += value.length;
|
|
531
|
+
if (binaryBytes > 8 * 1024 * 1024 || !value.every((byte) => Number.isInteger(byte) && byte >= 0 && byte <= 255)) return false;
|
|
532
|
+
continue;
|
|
533
|
+
}
|
|
528
534
|
if (value.length > 1e4) return false;
|
|
529
|
-
for (const child of value) pending.push({
|
|
535
|
+
for (const [index, child] of value.entries()) pending.push({
|
|
530
536
|
value: child,
|
|
531
|
-
|
|
537
|
+
path: [...path, String(index)]
|
|
532
538
|
});
|
|
533
539
|
continue;
|
|
534
540
|
}
|
|
535
541
|
if (typeof value !== "object") return false;
|
|
536
542
|
const entries = Object.entries(value);
|
|
537
543
|
if (entries.length > 1e4 || entries.some(([key]) => key.length > 256)) return false;
|
|
538
|
-
for (const [, child] of entries) pending.push({
|
|
544
|
+
for (const [key, child] of entries) pending.push({
|
|
539
545
|
value: child,
|
|
540
|
-
|
|
546
|
+
path: [...path, key]
|
|
541
547
|
});
|
|
542
548
|
}
|
|
543
549
|
return true;
|
|
@@ -586,11 +592,12 @@ function unhandledBackendFailure(startedAt) {
|
|
|
586
592
|
};
|
|
587
593
|
}
|
|
588
594
|
async function callOpenFairyGuiBackendTool(runtime, name, input, policy) {
|
|
589
|
-
if (!isOpenFairyGuiMcpPayloadWithinBudget(input)) throw new RangeError("MCP input exceeds the depth, node, key, string, or byte budget.");
|
|
590
595
|
const definition = OPENFAIRYGUI_BACKEND_TOOL_DEFINITIONS.find((entry) => entry.name === name);
|
|
591
596
|
if (!definition) throw new RangeError(`Unknown OpenFairyGUI backend MCP tool: ${name}`);
|
|
597
|
+
const bytePaths = CONTRACT_SNAPSHOT.tools[definition.backendMethod].bytePaths;
|
|
598
|
+
if (!isOpenFairyGuiMcpPayloadWithinBudget(input, bytePaths)) throw new RangeError("MCP input exceeds the depth, node, key, string, or byte budget.");
|
|
592
599
|
const parsed = definition.inputSchema.parse(input);
|
|
593
|
-
const decoded = decodeToolBytes(parsed,
|
|
600
|
+
const decoded = decodeToolBytes(parsed, bytePaths);
|
|
594
601
|
const startedAt = Date.now();
|
|
595
602
|
try {
|
|
596
603
|
let hostFailure = await policy?.beforeCall(structuredClone(parsed));
|
|
@@ -622,7 +629,7 @@ async function callOpenFairyGuiBackendTool(runtime, name, input, policy) {
|
|
|
622
629
|
//#region src/server.ts
|
|
623
630
|
const require$1 = (0, node_module.createRequire)(require("url").pathToFileURL(__filename).href);
|
|
624
631
|
function getInjectedPackageVersion() {
|
|
625
|
-
const version = "0.5.0-alpha.
|
|
632
|
+
const version = "0.5.0-alpha.4";
|
|
626
633
|
return typeof version === "string" && true ? version : null;
|
|
627
634
|
}
|
|
628
635
|
function readPackageVersion() {
|
|
@@ -478,16 +478,16 @@ const OPENFAIRYGUI_BACKEND_TOOL_METADATA = [
|
|
|
478
478
|
//#region src/tool-definitions.ts
|
|
479
479
|
const OPENFAIRYGUI_BACKEND_TOOL_PREFIX = "openfairygui_backend_";
|
|
480
480
|
const OPENFAIRYGUI_BACKEND_TOOL_NAMES = OPENFAIRYGUI_BACKEND_TOOL_METADATA.map((entry) => entry.name);
|
|
481
|
-
function isOpenFairyGuiMcpPayloadWithinBudget(root) {
|
|
481
|
+
function isOpenFairyGuiMcpPayloadWithinBudget(root, bytePaths = []) {
|
|
482
482
|
const pending = [{
|
|
483
483
|
value: root,
|
|
484
|
-
|
|
484
|
+
path: []
|
|
485
485
|
}];
|
|
486
|
-
let nodes = 0;
|
|
486
|
+
let nodes = 0, binaryBytes = 0;
|
|
487
487
|
while (pending.length > 0) {
|
|
488
|
-
const { value,
|
|
488
|
+
const { value, path } = pending.pop();
|
|
489
489
|
nodes += 1;
|
|
490
|
-
if (nodes > 1e5 ||
|
|
490
|
+
if (nodes > 1e5 || path.length > 32) return false;
|
|
491
491
|
if (value === null || typeof value === "boolean") continue;
|
|
492
492
|
if (typeof value === "number") {
|
|
493
493
|
if (!Number.isFinite(value)) return false;
|
|
@@ -498,23 +498,29 @@ function isOpenFairyGuiMcpPayloadWithinBudget(root) {
|
|
|
498
498
|
continue;
|
|
499
499
|
}
|
|
500
500
|
if (value instanceof Uint8Array) {
|
|
501
|
-
|
|
501
|
+
binaryBytes += value.byteLength;
|
|
502
|
+
if (binaryBytes > 8 * 1024 * 1024) return false;
|
|
502
503
|
continue;
|
|
503
504
|
}
|
|
504
505
|
if (Array.isArray(value)) {
|
|
506
|
+
if (bytePaths.some((parts) => parts.length === path.length && parts.every((part, index) => part === "*" || part === path[index]))) {
|
|
507
|
+
binaryBytes += value.length;
|
|
508
|
+
if (binaryBytes > 8 * 1024 * 1024 || !value.every((byte) => Number.isInteger(byte) && byte >= 0 && byte <= 255)) return false;
|
|
509
|
+
continue;
|
|
510
|
+
}
|
|
505
511
|
if (value.length > 1e4) return false;
|
|
506
|
-
for (const child of value) pending.push({
|
|
512
|
+
for (const [index, child] of value.entries()) pending.push({
|
|
507
513
|
value: child,
|
|
508
|
-
|
|
514
|
+
path: [...path, String(index)]
|
|
509
515
|
});
|
|
510
516
|
continue;
|
|
511
517
|
}
|
|
512
518
|
if (typeof value !== "object") return false;
|
|
513
519
|
const entries = Object.entries(value);
|
|
514
520
|
if (entries.length > 1e4 || entries.some(([key]) => key.length > 256)) return false;
|
|
515
|
-
for (const [, child] of entries) pending.push({
|
|
521
|
+
for (const [key, child] of entries) pending.push({
|
|
516
522
|
value: child,
|
|
517
|
-
|
|
523
|
+
path: [...path, key]
|
|
518
524
|
});
|
|
519
525
|
}
|
|
520
526
|
return true;
|
|
@@ -563,11 +569,12 @@ function unhandledBackendFailure(startedAt) {
|
|
|
563
569
|
};
|
|
564
570
|
}
|
|
565
571
|
async function callOpenFairyGuiBackendTool(runtime, name, input, policy) {
|
|
566
|
-
if (!isOpenFairyGuiMcpPayloadWithinBudget(input)) throw new RangeError("MCP input exceeds the depth, node, key, string, or byte budget.");
|
|
567
572
|
const definition = OPENFAIRYGUI_BACKEND_TOOL_DEFINITIONS.find((entry) => entry.name === name);
|
|
568
573
|
if (!definition) throw new RangeError(`Unknown OpenFairyGUI backend MCP tool: ${name}`);
|
|
574
|
+
const bytePaths = CONTRACT_SNAPSHOT.tools[definition.backendMethod].bytePaths;
|
|
575
|
+
if (!isOpenFairyGuiMcpPayloadWithinBudget(input, bytePaths)) throw new RangeError("MCP input exceeds the depth, node, key, string, or byte budget.");
|
|
569
576
|
const parsed = definition.inputSchema.parse(input);
|
|
570
|
-
const decoded = decodeToolBytes(parsed,
|
|
577
|
+
const decoded = decodeToolBytes(parsed, bytePaths);
|
|
571
578
|
const startedAt = Date.now();
|
|
572
579
|
try {
|
|
573
580
|
let hostFailure = await policy?.beforeCall(structuredClone(parsed));
|
|
@@ -599,7 +606,7 @@ async function callOpenFairyGuiBackendTool(runtime, name, input, policy) {
|
|
|
599
606
|
//#region src/server.ts
|
|
600
607
|
const require = createRequire(import.meta.url);
|
|
601
608
|
function getInjectedPackageVersion() {
|
|
602
|
-
const version = "0.5.0-alpha.
|
|
609
|
+
const version = "0.5.0-alpha.4";
|
|
603
610
|
return typeof version === "string" && true ? version : null;
|
|
604
611
|
}
|
|
605
612
|
function readPackageVersion() {
|
package/dist/stdio.cjs
CHANGED
package/dist/stdio.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { t as connectOpenFairyGuiMcpStdio } from "./stdio
|
|
1
|
+
import { t as connectOpenFairyGuiMcpStdio } from "./stdio-t-TXHfJJ.mjs";
|
|
2
2
|
export { connectOpenFairyGuiMcpStdio };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openfairygui/mcp",
|
|
3
|
-
"version": "0.5.0-alpha.
|
|
3
|
+
"version": "0.5.0-alpha.4",
|
|
4
4
|
"description": "FairyGUI Headless Authoring SDK - MCP server adapter for the backend runtime.",
|
|
5
5
|
"author": "OpenFairyGUI Contributors",
|
|
6
6
|
"license": "MIT",
|
|
@@ -61,13 +61,13 @@
|
|
|
61
61
|
"dependencies": {
|
|
62
62
|
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
63
63
|
"zod": "^4.3.6",
|
|
64
|
-
"@openfairygui/backend": "0.5.0-alpha.
|
|
64
|
+
"@openfairygui/backend": "0.5.0-alpha.4"
|
|
65
65
|
},
|
|
66
66
|
"devDependencies": {
|
|
67
67
|
"ava": "^7.0.0",
|
|
68
68
|
"tsx": "^4.0.0",
|
|
69
|
-
"@openfairygui/
|
|
70
|
-
"@openfairygui/
|
|
69
|
+
"@openfairygui/core": "0.5.0-alpha.4",
|
|
70
|
+
"@openfairygui/test-utils": "0.3.0"
|
|
71
71
|
},
|
|
72
72
|
"ava": {
|
|
73
73
|
"extensions": {
|
package/src/tool-definitions.ts
CHANGED
|
@@ -14,13 +14,13 @@ export interface OpenFairyGuiBackendToolDefinition extends BackendToolMetadata {
|
|
|
14
14
|
outputSchema: z.ZodObject;
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
-
export function isOpenFairyGuiMcpPayloadWithinBudget(root: unknown): boolean {
|
|
18
|
-
const pending: Array<{ value: unknown;
|
|
19
|
-
let nodes = 0;
|
|
17
|
+
export function isOpenFairyGuiMcpPayloadWithinBudget(root: unknown, bytePaths: readonly string[][] = []): boolean {
|
|
18
|
+
const pending: Array<{ value: unknown; path: string[] }> = [{ value: root, path: [] }];
|
|
19
|
+
let nodes = 0, binaryBytes = 0;
|
|
20
20
|
while (pending.length > 0) {
|
|
21
|
-
const { value,
|
|
21
|
+
const { value, path } = pending.pop()!;
|
|
22
22
|
nodes += 1;
|
|
23
|
-
if (nodes > 100_000 ||
|
|
23
|
+
if (nodes > 100_000 || path.length > 32) return false;
|
|
24
24
|
if (value === null || typeof value === 'boolean') continue;
|
|
25
25
|
if (typeof value === 'number') {
|
|
26
26
|
if (!Number.isFinite(value)) return false;
|
|
@@ -31,18 +31,24 @@ export function isOpenFairyGuiMcpPayloadWithinBudget(root: unknown): boolean {
|
|
|
31
31
|
continue;
|
|
32
32
|
}
|
|
33
33
|
if (value instanceof Uint8Array) {
|
|
34
|
-
|
|
34
|
+
binaryBytes += value.byteLength;
|
|
35
|
+
if (binaryBytes > 8 * 1024 * 1024) return false;
|
|
35
36
|
continue;
|
|
36
37
|
}
|
|
37
38
|
if (Array.isArray(value)) {
|
|
39
|
+
if (bytePaths.some((parts) => parts.length === path.length && parts.every((part, index) => part === '*' || part === path[index]))) {
|
|
40
|
+
binaryBytes += value.length;
|
|
41
|
+
if (binaryBytes > 8 * 1024 * 1024 || !value.every((byte) => Number.isInteger(byte) && byte >= 0 && byte <= 255)) return false;
|
|
42
|
+
continue;
|
|
43
|
+
}
|
|
38
44
|
if (value.length > 10_000) return false;
|
|
39
|
-
for (const child of value) pending.push({ value: child,
|
|
45
|
+
for (const [index, child] of value.entries()) pending.push({ value: child, path: [...path, String(index)] });
|
|
40
46
|
continue;
|
|
41
47
|
}
|
|
42
48
|
if (typeof value !== 'object') return false;
|
|
43
49
|
const entries = Object.entries(value);
|
|
44
50
|
if (entries.length > 10_000 || entries.some(([key]) => key.length > 256)) return false;
|
|
45
|
-
for (const [, child] of entries) pending.push({ value: child,
|
|
51
|
+
for (const [key, child] of entries) pending.push({ value: child, path: [...path, key] });
|
|
46
52
|
}
|
|
47
53
|
return true;
|
|
48
54
|
}
|
package/src/tool-handler.ts
CHANGED
|
@@ -74,13 +74,14 @@ export async function callOpenFairyGuiBackendTool(
|
|
|
74
74
|
input: Record<string, unknown>,
|
|
75
75
|
policy?: OpenFairyGuiMcpToolPolicy,
|
|
76
76
|
): Promise<CallToolResult> {
|
|
77
|
-
if (!isOpenFairyGuiMcpPayloadWithinBudget(input)) {
|
|
78
|
-
throw new RangeError('MCP input exceeds the depth, node, key, string, or byte budget.');
|
|
79
|
-
}
|
|
80
77
|
const definition = OPENFAIRYGUI_BACKEND_TOOL_DEFINITIONS.find((entry) => entry.name === name);
|
|
81
78
|
if (!definition) throw new RangeError(`Unknown OpenFairyGUI backend MCP tool: ${name}`);
|
|
79
|
+
const bytePaths = CONTRACT_SNAPSHOT.tools[definition.backendMethod].bytePaths;
|
|
80
|
+
if (!isOpenFairyGuiMcpPayloadWithinBudget(input, bytePaths)) {
|
|
81
|
+
throw new RangeError('MCP input exceeds the depth, node, key, string, or byte budget.');
|
|
82
|
+
}
|
|
82
83
|
const parsed = definition.inputSchema.parse(input) as Record<string, unknown>;
|
|
83
|
-
const decoded = decodeToolBytes(parsed,
|
|
84
|
+
const decoded = decodeToolBytes(parsed, bytePaths);
|
|
84
85
|
const startedAt = Date.now();
|
|
85
86
|
try {
|
|
86
87
|
let hostFailure = await policy?.beforeCall(structuredClone(parsed));
|