From 45cf4d7d4f3a1da99d525419f9885970fbd81ed7 Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 23 Oct 2026 21:33:37 +0000 Subject: [PATCH] Load workspace MCP tools independently so one bad resource can't drop the rest getAllToolsJsonForRoom wrapped each workspace tool loop (WORKSPACE_RESOURCE rows and CONFIG_JSON.mcps) in a single try/catch, so the first resource whose getToolJson threw - e.g. a knowledge base without MCP enabled, or a deleted engine - aborted the loop and silently dropped every tool after it. Because EditWorkspace writes engines before projects, saving an agent with a non-MCP vector engine could leave a chat with no tools at all. Catch per resource instead, mark failed ids as seen so the CONFIG_JSON pass doesn't retry them, and guard a null resource query result. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01CK6yNNgkxXZ5R81iaa1Lta --- src/prerna/engine/impl/model/Room.java | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/src/prerna/engine/impl/model/Room.java b/src/prerna/engine/impl/model/Room.java index 8dc4f3f01c..19b550d6a6 100644 --- a/src/prerna/engine/impl/model/Room.java +++ b/src/prerna/engine/impl/model/Room.java @@ -1372,11 +1372,18 @@ public List> getAllToolsJsonForRoom(int maxLength, boolean s List> tools = ModelInferenceLogsUtils.getWorkspaceResourcesIgnoringType( workspaceId, Arrays.asList(AbstractWorkspaceReactor.PROMPT_RESOURCE_TYPE, AbstractWorkspaceReactor.SKILL_RESOURCE_TYPE)); - for (Map tool : tools) { + for (Map tool : tools != null ? tools : List.>of()) { String toolId = (String) tool.get("resource_id"); - if (!ensureUnique.contains(toolId)) { - aggregated.addAll(getToolJson(toolId, maxLength, sanitizeToolNamesForLLM, lookup)); - ensureUnique.add(toolId); + // marked seen even on failure so CONFIG_JSON.mcps doesn't retry it + if (toolId != null && ensureUnique.add(toolId)) { + // one resource that can't produce tools (e.g. a knowledge base without + // MCP enabled) must not drop the workspace's remaining tools + try { + aggregated.addAll(getToolJson(toolId, maxLength, sanitizeToolNamesForLLM, lookup)); + } catch (Exception e) { + classLogger.warn("Skipping workspace mcp {} for workspaceId={}: {}", toolId, + workspaceId, e.getMessage()); + } } } } catch (Exception e) { @@ -1394,9 +1401,14 @@ public List> getAllToolsJsonForRoom(int maxLength, boolean s continue; } String toolId = mcp.optString("id", null); - if (toolId != null && !toolId.isEmpty() && !ensureUnique.contains(toolId)) { - aggregated.addAll(getToolJson(toolId, maxLength, sanitizeToolNamesForLLM, lookup)); - ensureUnique.add(toolId); + if (toolId != null && !toolId.isEmpty() && ensureUnique.add(toolId)) { + try { + aggregated.addAll( + getToolJson(toolId, maxLength, sanitizeToolNamesForLLM, lookup)); + } catch (Exception e) { + classLogger.warn("Skipping CONFIG_JSON mcp {} for workspaceId={}: {}", toolId, + workspaceId, e.getMessage()); + } } } }