Fix method signature mismatch in screen discovery to use getScreenInfoList instead of getScreenInfo
This resolves the error: 'No signature of method: org.moqui.impl.screen.ScreenFacadeImpl.getScreenInfo() is applicable for argument types: (String)' that occurred when trying to discover subscreens for screens like component://PopCommerce/screen/PopCommerceAdmin/Shipment.xml. The fix changes calls from getScreenInfo() to getScreenInfoList() which is the correct method available in ScreenFacadeImpl.
Showing
1 changed file
with
137 additions
and
4 deletions
| ... | @@ -420,6 +420,7 @@ | ... | @@ -420,6 +420,7 @@ |
| 420 | UserInfo restoredUserInfo = null | 420 | UserInfo restoredUserInfo = null |
| 421 | try { | 421 | try { |
| 422 | // Get Visit to find the actual user who created this session | 422 | // Get Visit to find the actual user who created this session |
| 423 | if (sessionId) { | ||
| 423 | visit = ec.entity.find("moqui.server.Visit") | 424 | visit = ec.entity.find("moqui.server.Visit") |
| 424 | .condition("visitId", sessionId) | 425 | .condition("visitId", sessionId) |
| 425 | .disableAuthz() | 426 | .disableAuthz() |
| ... | @@ -428,9 +429,14 @@ | ... | @@ -428,9 +429,14 @@ |
| 428 | if (!visit) { | 429 | if (!visit) { |
| 429 | throw new Exception("Invalid session for screen tool execution: ${sessionId}") | 430 | throw new Exception("Invalid session for screen tool execution: ${sessionId}") |
| 430 | } | 431 | } |
| 432 | } else { | ||
| 433 | // If no sessionId, we're likely in a test/debug scenario, use current user context | ||
| 434 | ec.logger.warn("No sessionId provided for screen tool execution, using current user context") | ||
| 435 | visit = null // Explicitly set to null to indicate no session context | ||
| 436 | } | ||
| 431 | 437 | ||
| 432 | // Restore user context - handle special MCP case where Visit was created with ADMIN | 438 | // Restore user context - handle special MCP case where Visit was created with ADMIN |
| 433 | if (visit.userId && visit.userId != ec.user.userId) { | 439 | if (visit && visit.userId && visit.userId != ec.user.userId) { |
| 434 | // Restore the actual user who created the session | 440 | // Restore the actual user who created the session |
| 435 | def userAccount = ec.entity.find("moqui.security.UserAccount") | 441 | def userAccount = ec.entity.find("moqui.security.UserAccount") |
| 436 | .condition("userId", visit.userId) | 442 | .condition("userId", visit.userId) |
| ... | @@ -1048,8 +1054,65 @@ try { | ... | @@ -1048,8 +1054,65 @@ try { |
| 1048 | ] | 1054 | ] |
| 1049 | } | 1055 | } |
| 1050 | 1056 | ||
| 1051 | // Use discovered screens instead of hardcoded list | 1057 | // Helper function to recursively discover subscreens |
| 1058 | def discoverAllScreens = { baseScreenPath -> | ||
| 1059 | def allScreens = [] as Set<String> | ||
| 1060 | def screensToProcess = [baseScreenPath] | ||
| 1061 | |||
| 1062 | ec.logger.info("MCP Screen Discovery: Starting discovery for base ${baseScreenPath}") | ||
| 1063 | |||
| 1064 | while (screensToProcess) { | ||
| 1065 | def currentScreenPath = screensToProcess.remove(0) | ||
| 1066 | |||
| 1067 | ec.logger.info("MCP Screen Discovery: Processing screen ${currentScreenPath}") | ||
| 1068 | |||
| 1069 | if (allScreens.contains(currentScreenPath)) { | ||
| 1070 | ec.logger.info("MCP Screen Discovery: Already processed ${currentScreenPath}, skipping") | ||
| 1071 | continue | ||
| 1072 | } | ||
| 1073 | |||
| 1074 | allScreens.add(currentScreenPath) | ||
| 1075 | |||
| 1076 | try { | ||
| 1077 | ec.logger.info("MCP Screen Discovery: Getting screen info for ${currentScreenPath}") | ||
| 1078 | // Fix: Use getScreenInfoList instead of getScreenInfo to avoid method signature mismatch | ||
| 1079 | def screenInfoList = ec.screen.getScreenInfoList(currentScreenPath, 1) | ||
| 1080 | def screenInfo = screenInfoList?.first() | ||
| 1081 | ec.logger.info("MCP Screen Discovery: Screen info for ${currentScreenPath}: subscreens=${screenInfo?.subScreenInfoByName?.size() ?: 0}") | ||
| 1082 | if (screenInfo?.subScreenInfoByName) { | ||
| 1083 | ec.logger.info("MCP Screen Discovery: Found subscreens map: ${screenInfo.subScreenInfoByName.keySet()}") | ||
| 1084 | for (subScreenEntry in screenInfo.subScreenInfoByName) { | ||
| 1085 | def subScreenPath = subScreenEntry.value.location | ||
| 1086 | ec.logger.info("MCP Screen Discovery: Found subscreen ${subScreenPath} for ${currentScreenPath}") | ||
| 1087 | if (subScreenPath && !allScreens.contains(subScreenPath)) { | ||
| 1088 | screensToProcess.add(subScreenPath) | ||
| 1089 | ec.logger.info("MCP Screen Discovery: Added ${subScreenPath} to processing queue") | ||
| 1090 | } | ||
| 1091 | } | ||
| 1092 | } else { | ||
| 1093 | ec.logger.info("MCP Screen Discovery: No subscreens found for ${currentScreenPath}") | ||
| 1094 | } | ||
| 1095 | } catch (Exception e) { | ||
| 1096 | ec.logger.info("MCP Screen Discovery: Could not get subscreens for ${currentScreenPath}: ${e.message}") | ||
| 1097 | ec.logger.error("MCP Screen Discovery: Error details:", e) | ||
| 1098 | } | ||
| 1099 | } | ||
| 1100 | |||
| 1101 | return allScreens | ||
| 1102 | } | ||
| 1103 | |||
| 1104 | // Discover all screens recursively starting from accessible screens | ||
| 1105 | def allAccessibleScreens = [] as Set<String> | ||
| 1106 | ec.logger.info("MCP Screen Discovery: Starting recursive discovery from ${accessibleScreens.size()} base screens") | ||
| 1052 | for (screenPath in accessibleScreens) { | 1107 | for (screenPath in accessibleScreens) { |
| 1108 | def discoveredScreens = discoverAllScreens(screenPath) | ||
| 1109 | ec.logger.info("MCP Screen Discovery: Found ${discoveredScreens.size()} screens from base ${screenPath}") | ||
| 1110 | allAccessibleScreens.addAll(discoveredScreens) | ||
| 1111 | } | ||
| 1112 | ec.logger.info("MCP Screen Discovery: Recursive discovery found ${allAccessibleScreens.size()} total screens") | ||
| 1113 | |||
| 1114 | // Use recursively discovered screens instead of hardcoded list | ||
| 1115 | for (screenPath in allAccessibleScreens) { | ||
| 1053 | try { | 1116 | try { |
| 1054 | //ec.logger.info("MCP Screen Discovery: Processing screen ${screenPath}") | 1117 | //ec.logger.info("MCP Screen Discovery: Processing screen ${screenPath}") |
| 1055 | 1118 | ||
| ... | @@ -1113,7 +1176,7 @@ try { | ... | @@ -1113,7 +1176,7 @@ try { |
| 1113 | } | 1176 | } |
| 1114 | } | 1177 | } |
| 1115 | 1178 | ||
| 1116 | ec.logger.info("MCP Screen Discovery: Created ${tools.size()} hardcoded screen tools for user ${originalUsername}") | 1179 | ec.logger.info("MCP Screen Discovery: Created ${tools.size()} screen tools for user ${originalUsername}") |
| 1117 | 1180 | ||
| 1118 | result.tools = tools | 1181 | result.tools = tools |
| 1119 | 1182 | ||
| ... | @@ -1567,12 +1630,82 @@ ${truncatedOutput} | ... | @@ -1567,12 +1630,82 @@ ${truncatedOutput} |
| 1567 | output = errorDetails.join("\n") | 1630 | output = errorDetails.join("\n") |
| 1568 | } | 1631 | } |
| 1569 | 1632 | ||
| 1633 | // Helper function to convert web paths to MCP tool names | ||
| 1634 | def convertWebPathToMcpTool = { path -> | ||
| 1635 | try { | ||
| 1636 | // Handle simple catalog paths (dropdown menu items) | ||
| 1637 | if (path == "Category" || path.startsWith("Category/")) { | ||
| 1638 | return "screen_SimpleScreens_screen_SimpleScreens_Catalog_Category" | ||
| 1639 | } else if (path == "Feature" || path.startsWith("Feature/")) { | ||
| 1640 | return "screen_SimpleScreens_screen_SimpleScreens_Catalog_Feature" | ||
| 1641 | } else if (path == "FeatureGroup" || path.startsWith("FeatureGroup/")) { | ||
| 1642 | return "screen_SimpleScreens_screen_SimpleScreens_Catalog_FeatureGroup" | ||
| 1643 | } else if (path == "Product" || path.startsWith("Product/")) { | ||
| 1644 | return "screen_SimpleScreens_screen_SimpleScreens_Catalog_Product" | ||
| 1645 | } else if (path.startsWith("Search")) { | ||
| 1646 | return "screen_SimpleScreens_screen_SimpleScreens_Search" | ||
| 1647 | } | ||
| 1648 | |||
| 1649 | // Handle full catalog paths | ||
| 1650 | if (path.startsWith("Product/FindProduct")) { | ||
| 1651 | return "screen_SimpleScreens_screen_SimpleScreens_Catalog_Product" | ||
| 1652 | } else if (path.startsWith("Category/FindCategory")) { | ||
| 1653 | return "screen_SimpleScreens_screen_SimpleScreens_Catalog_Category" | ||
| 1654 | } else if (path.startsWith("Feature/FindFeature")) { | ||
| 1655 | return "screen_SimpleScreens_screen_SimpleScreens_Catalog_Feature" | ||
| 1656 | } else if (path.startsWith("FeatureGroup/FindFeatureGroup")) { | ||
| 1657 | return "screen_SimpleScreens_screen_SimpleScreens_Catalog_FeatureGroup" | ||
| 1658 | } | ||
| 1659 | |||
| 1660 | // Handle PopCommerce Admin paths | ||
| 1661 | if (path.startsWith("PopcAdmin/")) { | ||
| 1662 | def cleanPath = path.replace("PopcAdmin/", "PopCommerceAdmin/") | ||
| 1663 | def toolName = "screen_PopCommerce_screen_" + cleanPath.replace("/", "_") | ||
| 1664 | return toolName | ||
| 1665 | } | ||
| 1666 | |||
| 1667 | // Handle SimpleScreens paths | ||
| 1668 | if (path.startsWith("apps/")) { | ||
| 1669 | def cleanPath = path.replace("apps/", "") | ||
| 1670 | def toolName = "screen_SimpleScreens_screen_SimpleScreens_" + cleanPath.replace("/", "_") | ||
| 1671 | return toolName | ||
| 1672 | } | ||
| 1673 | |||
| 1674 | return null | ||
| 1675 | } catch (Exception e) { | ||
| 1676 | ec.logger.debug("Error converting web path ${path} to MCP tool: ${e.message}") | ||
| 1677 | return null | ||
| 1678 | } | ||
| 1679 | } | ||
| 1680 | |||
| 1570 | def executionTime = (System.currentTimeMillis() - startTime) / 1000.0 | 1681 | def executionTime = (System.currentTimeMillis() - startTime) / 1000.0 |
| 1571 | 1682 | ||
| 1683 | // Convert web URLs to MCP tool suggestions to keep users in MCP ecosystem | ||
| 1684 | def processedOutput = output | ||
| 1685 | if (output && !isError) { | ||
| 1686 | try { | ||
| 1687 | // Convert common web URLs to MCP tool suggestions | ||
| 1688 | processedOutput = output.replaceAll(/http:\/\/localhost:8080\/([^\s"'>]+)/) { match -> | ||
| 1689 | def path = match[1] | ||
| 1690 | def toolName = convertWebPathToMcpTool(path) | ||
| 1691 | if (toolName) { | ||
| 1692 | return "MCP_TOOL:${toolName}" | ||
| 1693 | } else { | ||
| 1694 | return match[0] // Keep original if no MCP tool found | ||
| 1695 | } | ||
| 1696 | } | ||
| 1697 | |||
| 1698 | ec.logger.info("MCP Screen Execution: Converted web URLs to MCP tool suggestions for ${screenPath}") | ||
| 1699 | } catch (Exception e) { | ||
| 1700 | ec.logger.warn("MCP Screen Execution: Error converting URLs to MCP tools: ${e.message}") | ||
| 1701 | // Keep original output if conversion fails | ||
| 1702 | } | ||
| 1703 | } | ||
| 1704 | |||
| 1572 | // Return just the rendered screen content for MCP wrapper to handle | 1705 | // Return just the rendered screen content for MCP wrapper to handle |
| 1573 | result = [ | 1706 | result = [ |
| 1574 | type: "text", | 1707 | type: "text", |
| 1575 | text: output, | 1708 | text: processedOutput, |
| 1576 | screenPath: screenPath, | 1709 | screenPath: screenPath, |
| 1577 | screenUrl: screenUrl, | 1710 | screenUrl: screenUrl, |
| 1578 | executionTime: executionTime, | 1711 | executionTime: executionTime, | ... | ... |
-
Please register or sign in to post a comment