@openfairygui/mcp 0.4.0 → 0.5.0-alpha.1

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/README.md CHANGED
@@ -14,6 +14,8 @@ It maps the backend P2 runtime surface into MCP tools:
14
14
  - `getSession`
15
15
  - `getProjectOutline`
16
16
  - `queryEntity`
17
+ - `readSessionState`
18
+ - `readResourceBytes`
17
19
  - `validateSession`
18
20
  - `preflightTransaction`
19
21
  - `applyTransaction`
@@ -34,7 +36,7 @@ Each tool exposes a method-specific output schema for `structuredContent.backend
34
36
  - `error?`
35
37
  - `meta?`
36
38
 
37
- The factory advertises the fixed 18-method Backend catalog. Input/output schemas come from the canonical installed contract; discovery uses self-contained draft-07 `definitions`/`$ref` to reuse repeated structures without loosening the 41-operation union, call validators or input budgets. Installed operation documentation remains available through `openfairygui://contracts/operations` and `openfairygui://docs/index`.
39
+ The factory advertises the fixed 20-method Backend catalog. Input/output schemas come from the canonical installed contract; discovery uses self-contained draft-07 `definitions`/`$ref` to reuse repeated structures without loosening the 41-operation union, call validators or input budgets. Installed operation documentation remains available through `openfairygui://contracts/operations` and `openfairygui://docs/index`.
38
40
 
39
41
  P1 also registers MCP-native ergonomics around the same backend surface:
40
42
 
@@ -49,6 +51,8 @@ P1 also registers MCP-native ergonomics around the same backend surface:
49
51
  Resources return `application/json` text containing the unchanged backend result envelope. Parameterized polling remains tool-based: `getEvents` and `listJobs` are not exposed as resource URI query grammars.
50
52
  The project outline is revision-bound and exposes package, resource, folder, display-node, controller-page, and transition identities for transaction planning. It intentionally omits source bytes and full property payloads. `validateSession` returns the backend-owned read-only project validation report; the MCP adapter does not reinterpret its diagnostics.
51
53
 
54
+ `readSessionState` returns a detached public UAM model without primary asset bytes, plus the current edit revision and source-read diagnostics. `readResourceBytes` reads one already-loaded primary asset with a required matching revision. Neither reads storage or changes the session. Both tools enforce their native response limits and a separate 16 MiB complete MCP response limit; see the installed method schemas and [workflow](../backend/docs/workflow.md).
55
+
52
56
  It does **not** redefine transaction selectors, transaction operations, path policy, session semantics, job semantics, cache semantics, or backend error envelopes. Those remain owned by `@openfairygui/backend`, `@openfairygui/functions`, and `@openfairygui/core`.
53
57
 
54
58
  It also does **not** activate artifact publish/restore jobs, subscriptions, persistent jobs, or cache-as-source-of-truth behavior. MCP roots may be useful client context, but this package does not enforce roots or duplicate backend path canonicalization; backend path policy remains authoritative.
package/dist/index.cjs CHANGED
@@ -1,5 +1,5 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_stdio = require("./stdio-B0OU-oZC.cjs");
2
+ const require_stdio = require("./stdio-CB98zdOf.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.d.cts CHANGED
@@ -11,6 +11,8 @@ interface BackendToolMetadata {
11
11
  backendMethod: BackendMethodName$1;
12
12
  title: string;
13
13
  description: string;
14
+ /** Bound the complete CallToolResult JSON; bounded reads use compact text JSON. */
15
+ maxResponseBytes?: number;
14
16
  annotations: {
15
17
  readOnlyHint?: boolean;
16
18
  destructiveHint?: boolean;
@@ -78,6 +80,28 @@ declare const OPENFAIRYGUI_BACKEND_TOOL_METADATA: readonly [{
78
80
  readonly idempotentHint: true;
79
81
  readonly openWorldHint: false;
80
82
  };
83
+ }, {
84
+ readonly name: "openfairygui_backend_read_session_state";
85
+ readonly backendMethod: "readSessionState";
86
+ readonly title: "Read Session State";
87
+ readonly description: "Read a detached copy of the currently committed public UAM model without primary asset sourceBytes, with revision, dirty state and source-read diagnostics. Optional expectedRevision rejects stale reads. Does not hydrate, write, reserve history or guarantee downstream usability. Complete tool response is limited to 16 MiB.";
88
+ readonly maxResponseBytes: 16777216;
89
+ readonly annotations: {
90
+ readonly readOnlyHint: true;
91
+ readonly idempotentHint: true;
92
+ readonly openWorldHint: false;
93
+ };
94
+ }, {
95
+ readonly name: "openfairygui_backend_read_resource_bytes";
96
+ readonly backendMethod: "readResourceBytes";
97
+ readonly title: "Read Resource Bytes";
98
+ readonly description: "Read a detached copy of one asset resource primary sourceBytes already held in the session, using exact packageId/resourceId and the required model edit revision. No filesystem hydration or auxiliary-file discovery. Stale reads require restarting the model/bytes read. Complete tool response is limited to 16 MiB.";
99
+ readonly maxResponseBytes: 16777216;
100
+ readonly annotations: {
101
+ readonly readOnlyHint: true;
102
+ readonly idempotentHint: true;
103
+ readonly openWorldHint: false;
104
+ };
81
105
  }, {
82
106
  readonly name: "openfairygui_backend_validate_session";
83
107
  readonly backendMethod: "validateSession";
@@ -206,7 +230,7 @@ declare const OPENFAIRYGUI_BACKEND_TOOL_METADATA: readonly [{
206
230
  //#region src/tool-definitions.d.ts
207
231
  declare const OPENFAIRYGUI_BACKEND_TOOL_PREFIX = "openfairygui_backend_";
208
232
  type OpenFairyGuiBackendToolName = typeof OPENFAIRYGUI_BACKEND_TOOL_METADATA[number]['name'];
209
- declare const OPENFAIRYGUI_BACKEND_TOOL_NAMES: ("openfairygui_backend_get_capabilities" | "openfairygui_backend_open_session" | "openfairygui_backend_open_project_session" | "openfairygui_backend_get_session" | "openfairygui_backend_get_project_outline" | "openfairygui_backend_query_entity" | "openfairygui_backend_validate_session" | "openfairygui_backend_preflight_transaction" | "openfairygui_backend_apply_transaction" | "openfairygui_backend_save_session" | "openfairygui_backend_materialize_session" | "openfairygui_backend_close_session" | "openfairygui_backend_get_events" | "openfairygui_backend_get_job" | "openfairygui_backend_list_jobs" | "openfairygui_backend_cancel_job" | "openfairygui_backend_get_cache_snapshot" | "openfairygui_backend_refresh_cache")[];
233
+ declare const OPENFAIRYGUI_BACKEND_TOOL_NAMES: ("openfairygui_backend_get_capabilities" | "openfairygui_backend_open_session" | "openfairygui_backend_open_project_session" | "openfairygui_backend_get_session" | "openfairygui_backend_get_project_outline" | "openfairygui_backend_query_entity" | "openfairygui_backend_read_session_state" | "openfairygui_backend_read_resource_bytes" | "openfairygui_backend_validate_session" | "openfairygui_backend_preflight_transaction" | "openfairygui_backend_apply_transaction" | "openfairygui_backend_save_session" | "openfairygui_backend_materialize_session" | "openfairygui_backend_close_session" | "openfairygui_backend_get_events" | "openfairygui_backend_get_job" | "openfairygui_backend_list_jobs" | "openfairygui_backend_cancel_job" | "openfairygui_backend_get_cache_snapshot" | "openfairygui_backend_refresh_cache")[];
210
234
  interface OpenFairyGuiBackendToolDefinition extends BackendToolMetadata {
211
235
  name: OpenFairyGuiBackendToolName;
212
236
  inputSchema: z.ZodObject;
package/dist/index.d.mts CHANGED
@@ -11,6 +11,8 @@ interface BackendToolMetadata {
11
11
  backendMethod: BackendMethodName$1;
12
12
  title: string;
13
13
  description: string;
14
+ /** Bound the complete CallToolResult JSON; bounded reads use compact text JSON. */
15
+ maxResponseBytes?: number;
14
16
  annotations: {
15
17
  readOnlyHint?: boolean;
16
18
  destructiveHint?: boolean;
@@ -78,6 +80,28 @@ declare const OPENFAIRYGUI_BACKEND_TOOL_METADATA: readonly [{
78
80
  readonly idempotentHint: true;
79
81
  readonly openWorldHint: false;
80
82
  };
83
+ }, {
84
+ readonly name: "openfairygui_backend_read_session_state";
85
+ readonly backendMethod: "readSessionState";
86
+ readonly title: "Read Session State";
87
+ readonly description: "Read a detached copy of the currently committed public UAM model without primary asset sourceBytes, with revision, dirty state and source-read diagnostics. Optional expectedRevision rejects stale reads. Does not hydrate, write, reserve history or guarantee downstream usability. Complete tool response is limited to 16 MiB.";
88
+ readonly maxResponseBytes: 16777216;
89
+ readonly annotations: {
90
+ readonly readOnlyHint: true;
91
+ readonly idempotentHint: true;
92
+ readonly openWorldHint: false;
93
+ };
94
+ }, {
95
+ readonly name: "openfairygui_backend_read_resource_bytes";
96
+ readonly backendMethod: "readResourceBytes";
97
+ readonly title: "Read Resource Bytes";
98
+ readonly description: "Read a detached copy of one asset resource primary sourceBytes already held in the session, using exact packageId/resourceId and the required model edit revision. No filesystem hydration or auxiliary-file discovery. Stale reads require restarting the model/bytes read. Complete tool response is limited to 16 MiB.";
99
+ readonly maxResponseBytes: 16777216;
100
+ readonly annotations: {
101
+ readonly readOnlyHint: true;
102
+ readonly idempotentHint: true;
103
+ readonly openWorldHint: false;
104
+ };
81
105
  }, {
82
106
  readonly name: "openfairygui_backend_validate_session";
83
107
  readonly backendMethod: "validateSession";
@@ -206,7 +230,7 @@ declare const OPENFAIRYGUI_BACKEND_TOOL_METADATA: readonly [{
206
230
  //#region src/tool-definitions.d.ts
207
231
  declare const OPENFAIRYGUI_BACKEND_TOOL_PREFIX = "openfairygui_backend_";
208
232
  type OpenFairyGuiBackendToolName = typeof OPENFAIRYGUI_BACKEND_TOOL_METADATA[number]['name'];
209
- declare const OPENFAIRYGUI_BACKEND_TOOL_NAMES: ("openfairygui_backend_get_capabilities" | "openfairygui_backend_open_session" | "openfairygui_backend_open_project_session" | "openfairygui_backend_get_session" | "openfairygui_backend_get_project_outline" | "openfairygui_backend_query_entity" | "openfairygui_backend_validate_session" | "openfairygui_backend_preflight_transaction" | "openfairygui_backend_apply_transaction" | "openfairygui_backend_save_session" | "openfairygui_backend_materialize_session" | "openfairygui_backend_close_session" | "openfairygui_backend_get_events" | "openfairygui_backend_get_job" | "openfairygui_backend_list_jobs" | "openfairygui_backend_cancel_job" | "openfairygui_backend_get_cache_snapshot" | "openfairygui_backend_refresh_cache")[];
233
+ declare const OPENFAIRYGUI_BACKEND_TOOL_NAMES: ("openfairygui_backend_get_capabilities" | "openfairygui_backend_open_session" | "openfairygui_backend_open_project_session" | "openfairygui_backend_get_session" | "openfairygui_backend_get_project_outline" | "openfairygui_backend_query_entity" | "openfairygui_backend_read_session_state" | "openfairygui_backend_read_resource_bytes" | "openfairygui_backend_validate_session" | "openfairygui_backend_preflight_transaction" | "openfairygui_backend_apply_transaction" | "openfairygui_backend_save_session" | "openfairygui_backend_materialize_session" | "openfairygui_backend_close_session" | "openfairygui_backend_get_events" | "openfairygui_backend_get_job" | "openfairygui_backend_list_jobs" | "openfairygui_backend_cancel_job" | "openfairygui_backend_get_cache_snapshot" | "openfairygui_backend_refresh_cache")[];
210
234
  interface OpenFairyGuiBackendToolDefinition extends BackendToolMetadata {
211
235
  name: OpenFairyGuiBackendToolName;
212
236
  inputSchema: z.ZodObject;
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-9ka7bvOr.mjs";
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-BNobuRxx.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 };
@@ -304,6 +304,30 @@ const OPENFAIRYGUI_BACKEND_TOOL_METADATA = [
304
304
  openWorldHint: false
305
305
  }
306
306
  },
307
+ {
308
+ name: "openfairygui_backend_read_session_state",
309
+ backendMethod: "readSessionState",
310
+ title: "Read Session State",
311
+ description: "Read a detached copy of the currently committed public UAM model without primary asset sourceBytes, with revision, dirty state and source-read diagnostics. Optional expectedRevision rejects stale reads. Does not hydrate, write, reserve history or guarantee downstream usability. Complete tool response is limited to 16 MiB.",
312
+ maxResponseBytes: 16777216,
313
+ annotations: {
314
+ readOnlyHint: true,
315
+ idempotentHint: true,
316
+ openWorldHint: false
317
+ }
318
+ },
319
+ {
320
+ name: "openfairygui_backend_read_resource_bytes",
321
+ backendMethod: "readResourceBytes",
322
+ title: "Read Resource Bytes",
323
+ description: "Read a detached copy of one asset resource primary sourceBytes already held in the session, using exact packageId/resourceId and the required model edit revision. No filesystem hydration or auxiliary-file discovery. Stale reads require restarting the model/bytes read. Complete tool response is limited to 16 MiB.",
324
+ maxResponseBytes: 16777216,
325
+ annotations: {
326
+ readOnlyHint: true,
327
+ idempotentHint: true,
328
+ openWorldHint: false
329
+ }
330
+ },
307
331
  {
308
332
  name: "openfairygui_backend_validate_session",
309
333
  backendMethod: "validateSession",
@@ -495,8 +519,8 @@ const OPENFAIRYGUI_BACKEND_TOOL_DEFINITIONS = OPENFAIRYGUI_BACKEND_TOOL_METADATA
495
519
  });
496
520
  //#endregion
497
521
  //#region src/tool-handler.ts
498
- function jsonResult(payload, isError = false) {
499
- const text = JSON.stringify(payload, (_key, value) => value instanceof Uint8Array ? [...value] : value, 2);
522
+ function jsonResult(payload, isError = false, compact = false) {
523
+ const text = JSON.stringify(payload, (_key, value) => value instanceof Uint8Array ? [...value] : value, compact ? void 0 : 2);
500
524
  const wirePayload = JSON.parse(text);
501
525
  return {
502
526
  content: [{
@@ -536,7 +560,15 @@ async function callOpenFairyGuiBackendTool(runtime, name, input) {
536
560
  const startedAt = Date.now();
537
561
  try {
538
562
  const result = await Reflect.apply(runtime[definition.backendMethod], runtime, definition.backendMethod === "getCapabilities" ? [] : [decoded]);
539
- const response = jsonResult(result, isBackendFailure(result));
563
+ let response = jsonResult(result, isBackendFailure(result), definition.maxResponseBytes !== void 0);
564
+ if (definition.maxResponseBytes !== void 0 && new TextEncoder().encode(JSON.stringify(response)).byteLength > definition.maxResponseBytes) response = jsonResult({
565
+ ...unhandledBackendFailure(startedAt),
566
+ error: {
567
+ code: "mcp_response_budget_exceeded",
568
+ message: "The complete MCP tool response exceeds its byte limit.",
569
+ maxBytes: definition.maxResponseBytes
570
+ }
571
+ }, true);
540
572
  definition.outputSchema.parse(response.structuredContent);
541
573
  return response;
542
574
  } catch {
@@ -547,7 +579,7 @@ async function callOpenFairyGuiBackendTool(runtime, name, input) {
547
579
  //#region src/server.ts
548
580
  const require = createRequire(import.meta.url);
549
581
  function getInjectedPackageVersion() {
550
- const version = "0.4.0";
582
+ const version = "0.5.0-alpha.1";
551
583
  return typeof version === "string" && true ? version : null;
552
584
  }
553
585
  function readPackageVersion() {
@@ -327,6 +327,30 @@ const OPENFAIRYGUI_BACKEND_TOOL_METADATA = [
327
327
  openWorldHint: false
328
328
  }
329
329
  },
330
+ {
331
+ name: "openfairygui_backend_read_session_state",
332
+ backendMethod: "readSessionState",
333
+ title: "Read Session State",
334
+ description: "Read a detached copy of the currently committed public UAM model without primary asset sourceBytes, with revision, dirty state and source-read diagnostics. Optional expectedRevision rejects stale reads. Does not hydrate, write, reserve history or guarantee downstream usability. Complete tool response is limited to 16 MiB.",
335
+ maxResponseBytes: 16777216,
336
+ annotations: {
337
+ readOnlyHint: true,
338
+ idempotentHint: true,
339
+ openWorldHint: false
340
+ }
341
+ },
342
+ {
343
+ name: "openfairygui_backend_read_resource_bytes",
344
+ backendMethod: "readResourceBytes",
345
+ title: "Read Resource Bytes",
346
+ description: "Read a detached copy of one asset resource primary sourceBytes already held in the session, using exact packageId/resourceId and the required model edit revision. No filesystem hydration or auxiliary-file discovery. Stale reads require restarting the model/bytes read. Complete tool response is limited to 16 MiB.",
347
+ maxResponseBytes: 16777216,
348
+ annotations: {
349
+ readOnlyHint: true,
350
+ idempotentHint: true,
351
+ openWorldHint: false
352
+ }
353
+ },
330
354
  {
331
355
  name: "openfairygui_backend_validate_session",
332
356
  backendMethod: "validateSession",
@@ -518,8 +542,8 @@ const OPENFAIRYGUI_BACKEND_TOOL_DEFINITIONS = OPENFAIRYGUI_BACKEND_TOOL_METADATA
518
542
  });
519
543
  //#endregion
520
544
  //#region src/tool-handler.ts
521
- function jsonResult(payload, isError = false) {
522
- const text = JSON.stringify(payload, (_key, value) => value instanceof Uint8Array ? [...value] : value, 2);
545
+ function jsonResult(payload, isError = false, compact = false) {
546
+ const text = JSON.stringify(payload, (_key, value) => value instanceof Uint8Array ? [...value] : value, compact ? void 0 : 2);
523
547
  const wirePayload = JSON.parse(text);
524
548
  return {
525
549
  content: [{
@@ -559,7 +583,15 @@ async function callOpenFairyGuiBackendTool(runtime, name, input) {
559
583
  const startedAt = Date.now();
560
584
  try {
561
585
  const result = await Reflect.apply(runtime[definition.backendMethod], runtime, definition.backendMethod === "getCapabilities" ? [] : [decoded]);
562
- const response = jsonResult(result, isBackendFailure(result));
586
+ let response = jsonResult(result, isBackendFailure(result), definition.maxResponseBytes !== void 0);
587
+ if (definition.maxResponseBytes !== void 0 && new TextEncoder().encode(JSON.stringify(response)).byteLength > definition.maxResponseBytes) response = jsonResult({
588
+ ...unhandledBackendFailure(startedAt),
589
+ error: {
590
+ code: "mcp_response_budget_exceeded",
591
+ message: "The complete MCP tool response exceeds its byte limit.",
592
+ maxBytes: definition.maxResponseBytes
593
+ }
594
+ }, true);
563
595
  definition.outputSchema.parse(response.structuredContent);
564
596
  return response;
565
597
  } catch {
@@ -570,7 +602,7 @@ async function callOpenFairyGuiBackendTool(runtime, name, input) {
570
602
  //#region src/server.ts
571
603
  const require$1 = (0, node_module.createRequire)(require("url").pathToFileURL(__filename).href);
572
604
  function getInjectedPackageVersion() {
573
- const version = "0.4.0";
605
+ const version = "0.5.0-alpha.1";
574
606
  return typeof version === "string" && true ? version : null;
575
607
  }
576
608
  function readPackageVersion() {
package/dist/stdio.cjs CHANGED
@@ -1,3 +1,3 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_stdio = require("./stdio-B0OU-oZC.cjs");
2
+ const require_stdio = require("./stdio-CB98zdOf.cjs");
3
3
  exports.connectOpenFairyGuiMcpStdio = require_stdio.connectOpenFairyGuiMcpStdio;
package/dist/stdio.mjs CHANGED
@@ -1,2 +1,2 @@
1
- import { t as connectOpenFairyGuiMcpStdio } from "./stdio-9ka7bvOr.mjs";
1
+ import { t as connectOpenFairyGuiMcpStdio } from "./stdio-BNobuRxx.mjs";
2
2
  export { connectOpenFairyGuiMcpStdio };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openfairygui/mcp",
3
- "version": "0.4.0",
3
+ "version": "0.5.0-alpha.1",
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.4.0"
64
+ "@openfairygui/backend": "0.5.0-alpha.1"
65
65
  },
66
66
  "devDependencies": {
67
67
  "ava": "^7.0.0",
68
68
  "tsx": "^4.0.0",
69
- "@openfairygui/core": "0.4.0",
70
- "@openfairygui/test-utils": "0.3.0"
69
+ "@openfairygui/test-utils": "0.3.0",
70
+ "@openfairygui/core": "0.5.0-alpha.1"
71
71
  },
72
72
  "ava": {
73
73
  "extensions": {
@@ -12,12 +12,12 @@ import {
12
12
  } from './tool-definitions.js';
13
13
 
14
14
  import { decodeToolBytes, CONTRACT_SNAPSHOT } from './contract-schema.js';
15
- import type { McpUnhandledFailure } from './tool-metadata.js';
15
+ import type { McpUnhandledFailure, McpResponseBudgetFailure } from './tool-metadata.js';
16
16
 
17
17
  export type OpenFairyGuiBackendRuntime = Pick<BackendRuntime, BackendMethodName>;
18
18
 
19
- function jsonResult(payload: unknown, isError = false): CallToolResult {
20
- const text = JSON.stringify(payload, (_key, value) => value instanceof Uint8Array ? [...value] : value, 2);
19
+ function jsonResult(payload: unknown, isError = false, compact = false): CallToolResult {
20
+ const text = JSON.stringify(payload, (_key, value) => value instanceof Uint8Array ? [...value] : value, compact ? undefined : 2);
21
21
  const wirePayload = JSON.parse(text) as unknown;
22
22
  return {
23
23
  content: [
@@ -74,7 +74,13 @@ export async function callOpenFairyGuiBackendTool(
74
74
  const startedAt = Date.now();
75
75
  try {
76
76
  const result = await Reflect.apply(runtime[definition.backendMethod], runtime, definition.backendMethod === 'getCapabilities' ? [] : [decoded]);
77
- const response = jsonResult(result, isBackendFailure(result));
77
+ let response = jsonResult(result, isBackendFailure(result), definition.maxResponseBytes !== undefined);
78
+ if (definition.maxResponseBytes !== undefined && new TextEncoder().encode(JSON.stringify(response)).byteLength > definition.maxResponseBytes) {
79
+ response = jsonResult({
80
+ ...unhandledBackendFailure(startedAt),
81
+ error: { code: 'mcp_response_budget_exceeded', message: 'The complete MCP tool response exceeds its byte limit.', maxBytes: definition.maxResponseBytes },
82
+ } satisfies McpResponseBudgetFailure, true);
83
+ }
78
84
  definition.outputSchema.parse(response.structuredContent);
79
85
  return response;
80
86
  } catch {
@@ -5,6 +5,8 @@ export interface BackendToolMetadata {
5
5
  backendMethod: BackendMethodName;
6
6
  title: string;
7
7
  description: string;
8
+ /** Bound the complete CallToolResult JSON; bounded reads use compact text JSON. */
9
+ maxResponseBytes?: number;
8
10
  annotations: {
9
11
  readOnlyHint?: boolean;
10
12
  destructiveHint?: boolean;
@@ -20,6 +22,12 @@ export interface McpUnhandledFailure {
20
22
  error: { code: 'backend_unhandled_error'; message: string };
21
23
  }
22
24
 
25
+ export interface McpResponseBudgetFailure {
26
+ ok: false;
27
+ meta: BackendResponseMeta;
28
+ error: { code: 'mcp_response_budget_exceeded'; message: string; maxBytes: number };
29
+ }
30
+
23
31
  /** Host objects cannot cross JSON; materialize keeps its existing MCP target boundary. */
24
32
  export const MCP_OMITTED_INPUT_FIELDS = {
25
33
  openProjectSession: ['storage'],
@@ -70,6 +78,22 @@ export const OPENFAIRYGUI_BACKEND_TOOL_METADATA = [
70
78
  description: 'Read revision-bound project/package settings, resource, component-property, display-node, controller (including pages/actions), or transition (including items) snapshots. Project queries use only kind; other queries use formal selectors. Settings snapshots include the complete settings payload for updateProjectSettings/updatePackageSettings. No source bytes; fixed projection with explicit response limits.',
71
79
  annotations: { readOnlyHint: true, idempotentHint: true, openWorldHint: false },
72
80
  },
81
+ {
82
+ name: 'openfairygui_backend_read_session_state',
83
+ backendMethod: 'readSessionState',
84
+ title: 'Read Session State',
85
+ description: 'Read a detached copy of the currently committed public UAM model without primary asset sourceBytes, with revision, dirty state and source-read diagnostics. Optional expectedRevision rejects stale reads. Does not hydrate, write, reserve history or guarantee downstream usability. Complete tool response is limited to 16 MiB.',
86
+ maxResponseBytes: 16777216,
87
+ annotations: { readOnlyHint: true, idempotentHint: true, openWorldHint: false },
88
+ },
89
+ {
90
+ name: 'openfairygui_backend_read_resource_bytes',
91
+ backendMethod: 'readResourceBytes',
92
+ title: 'Read Resource Bytes',
93
+ description: 'Read a detached copy of one asset resource primary sourceBytes already held in the session, using exact packageId/resourceId and the required model edit revision. No filesystem hydration or auxiliary-file discovery. Stale reads require restarting the model/bytes read. Complete tool response is limited to 16 MiB.',
94
+ maxResponseBytes: 16777216,
95
+ annotations: { readOnlyHint: true, idempotentHint: true, openWorldHint: false },
96
+ },
73
97
  {
74
98
  name: 'openfairygui_backend_validate_session',
75
99
  backendMethod: 'validateSession',