blueprint-extractor-mcp 4.0.0 → 4.2.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.
@@ -6,7 +6,10 @@ export async function callSubsystemJson(client, method, params, options) {
6
6
  }
7
7
  const parsed = JSON.parse(result);
8
8
  if (typeof parsed.error === 'string' && parsed.error.length > 0) {
9
- const err = new Error(parsed.error);
9
+ const errorText = parsed.error === 'Unknown error'
10
+ ? `C++ subsystem returned generic "Unknown error" for ${method}(${Object.keys(params).join(', ')}). Check UE editor Output Log for the actual exception.`
11
+ : parsed.error;
12
+ const err = new Error(errorText);
10
13
  err.ueResponse = parsed;
11
14
  throw err;
12
15
  }
@@ -70,8 +70,9 @@ export function classifyRecoverableToolFailure(toolName, message, payload) {
70
70
  recoverable: true,
71
71
  retry_after_ms: EDITOR_POLL_INTERVAL_MS,
72
72
  next_steps: [
73
- 'Call wait_for_editor to confirm the editor has fully reconnected after the restart window.',
74
- 'If the editor is connected but this persists, verify the BlueprintExtractor plugin/subsystem loaded successfully and retry the same tool.',
73
+ 'Call wait_for_editor to confirm the editor has fully reconnected.',
74
+ 'If a write operation (patch_class_defaults, modify_blueprint_members, etc.) was in progress, the editor may have crashed. Check the editor log and consider `git checkout` to recover modified assets.',
75
+ 'Use restart_editor with force_kill: true if the editor process is unresponsive.',
75
76
  ],
76
77
  };
77
78
  }
@@ -84,13 +84,27 @@ export function registerBlueprintAuthoringTools({ server, callSubsystemJson, jso
84
84
  }, async (args) => {
85
85
  try {
86
86
  const { asset_path, operation, payload, validate_only } = args;
87
+ const extraContent = [];
88
+ if (operation === 'patch_class_defaults' && payload?.classDefaults) {
89
+ const classDefaults = payload.classDefaults;
90
+ const warnings = [];
91
+ for (const [key, value] of Object.entries(classDefaults)) {
92
+ if (typeof value === 'object' && value !== null && !Array.isArray(value)) {
93
+ warnings.push(`Property '${key}': value is a nested object. If setting a component reference ` +
94
+ `or asset path, use a string path (e.g., "/Game/Path/Asset.Asset") instead.`);
95
+ }
96
+ }
97
+ if (warnings.length > 0) {
98
+ extraContent.push({ type: 'text', text: `Warnings:\n${warnings.join('\n')}` });
99
+ }
100
+ }
87
101
  const parsed = await callSubsystemJson('ModifyBlueprintMembers', {
88
102
  AssetPath: asset_path,
89
103
  Operation: operation,
90
104
  PayloadJson: JSON.stringify(payload ?? {}),
91
105
  bValidateOnly: validate_only,
92
106
  });
93
- return jsonToolSuccess(parsed);
107
+ return jsonToolSuccess(parsed, { extraContent });
94
108
  }
95
109
  catch (error) {
96
110
  return jsonToolError(error);
@@ -50,15 +50,14 @@ export function registerExtractionTools({ server, callSubsystemJson, scopeEnum,
50
50
  parsed = compactBlueprint(parsed);
51
51
  }
52
52
  const text = compact ? JSON.stringify(parsed) : JSON.stringify(parsed, null, 2);
53
+ const extraContent = [];
53
54
  if (text.length > 200_000) {
54
- return {
55
- content: [{
56
- type: 'text',
57
- text: `Warning: Response is ${(text.length / 1024).toFixed(0)}KB — consider using a narrower scope (ClassLevel, Variables, or FunctionsShallow).\n\n${text.substring(0, 200_000)}...\n[TRUNCATED]`,
58
- }],
59
- };
55
+ extraContent.push({
56
+ type: 'text',
57
+ text: `Warning: Response is ${(text.length / 1024).toFixed(0)}KB (${text.length} chars). Consider using a narrower scope (ClassLevel, Variables, or FunctionsShallow) first, then Full with graph_filter for specific functions.`,
58
+ });
60
59
  }
61
- return jsonToolSuccess(parsed);
60
+ return jsonToolSuccess(parsed, { extraContent });
62
61
  }
63
62
  catch (error) {
64
63
  return jsonToolError(error);
@@ -90,18 +89,17 @@ export function registerExtractionTools({ server, callSubsystemJson, scopeEnum,
90
89
  break;
91
90
  }
92
91
  }
92
+ const extraContent = [];
93
93
  if (asset_type === 'data_table') {
94
94
  const text = JSON.stringify(parsed, null, 2);
95
95
  if (text.length > 200_000) {
96
- return {
97
- content: [{
98
- type: 'text',
99
- text: `Warning: Response is ${(text.length / 1024).toFixed(0)}KB — large DataTable.\n\n${text.substring(0, 200_000)}...\n[TRUNCATED]`,
100
- }],
101
- };
96
+ extraContent.push({
97
+ type: 'text',
98
+ text: `Warning: Response is ${(text.length / 1024).toFixed(0)}KB (${text.length} chars) — large DataTable. Consider filtering rows or extracting a subset.`,
99
+ });
102
100
  }
103
101
  }
104
- return jsonToolSuccess(parsed);
102
+ return jsonToolSuccess(parsed, { extraContent });
105
103
  }
106
104
  catch (error) {
107
105
  return jsonToolError(error);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "blueprint-extractor-mcp",
3
- "version": "4.0.0",
3
+ "version": "4.2.0",
4
4
  "description": "MCP server for the Unreal Engine BlueprintExtractor plugin over Remote Control",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",