Fix MCP screen discovery closure and JSON-RPC response nesting
- Separate processScreenWithSubscreens closure definition to fix Groovy closure scope issues - Add proper flattening of subScreenPathList to handle nested collections - Fix subscreen tool naming with dot notation for parent.child relationships - Enhance screen tool execution to support subscreen parameters - Unwrap Moqui service results in EnhancedMcpServlet to avoid double nesting in JSON-RPC responses - Improve error handling and logging throughout screen discovery process Now successfully discovers 29 total tools (17 screen tools + 12 service tools) with proper session management.
Showing
3 changed files
with
30 additions
and
5 deletions
This diff is collapsed.
Click to expand it.
| ... | @@ -150,10 +150,12 @@ class CustomScreenTestImpl implements McpScreenTest { | ... | @@ -150,10 +150,12 @@ class CustomScreenTestImpl implements McpScreenTest { |
| 150 | void renderAll(List<String> screenPathList, Map<String, Object> parameters, String requestMethod) { | 150 | void renderAll(List<String> screenPathList, Map<String, Object> parameters, String requestMethod) { |
| 151 | // NOTE: using single thread for now, doesn't actually make a lot of difference in overall test run time | 151 | // NOTE: using single thread for now, doesn't actually make a lot of difference in overall test run time |
| 152 | int threads = 1 | 152 | int threads = 1 |
| 153 | def output | ||
| 153 | if (threads == 1) { | 154 | if (threads == 1) { |
| 154 | for (String screenPath in screenPathList) { | 155 | for (String screenPath in screenPathList) { |
| 155 | McpScreenTestRender str = render(screenPath, parameters, requestMethod) | 156 | McpScreenTestRender str = render(screenPath, parameters, requestMethod) |
| 156 | logger.info("Rendered ${screenPath} in ${str.getRenderTime()}ms, ${str.getOutput()?.length()} characters") | 157 | output = str.getOutput() |
| 158 | logger.info("Rendered ${screenPath} in ${str.getRenderTime()}ms, ${output?.length()} characters") | ||
| 157 | } | 159 | } |
| 158 | } else { | 160 | } else { |
| 159 | ExecutionContextImpl eci = ecfi.getEci() | 161 | ExecutionContextImpl eci = ecfi.getEci() |
| ... | @@ -264,8 +266,26 @@ class CustomScreenTestImpl implements McpScreenTest { | ... | @@ -264,8 +266,26 @@ class CustomScreenTestImpl implements McpScreenTest { |
| 264 | long startTime = System.currentTimeMillis() | 266 | long startTime = System.currentTimeMillis() |
| 265 | 267 | ||
| 266 | // parse the screenPath | 268 | // parse the screenPath |
| 267 | ArrayList<String> screenPathList = ScreenUrlInfo.parseSubScreenPath(csti.rootScreenDef, csti.baseScreenDef, | 269 | def screenPathList |
| 270 | // Special handling for non-webroot root screens with subscreens | ||
| 271 | if (csti.rootScreenLocation != null && !csti.rootScreenLocation.contains("webroot.xml") && stri.screenPath.contains('/')) { | ||
| 272 | // For non-webroot roots with subscreens, build path list directly | ||
| 273 | // rootScreenDef is the parent screen, screenPath is the subscreen path | ||
| 274 | screenPathList = new ArrayList<>() | ||
| 275 | // Add root screen path (already a full component:// path) | ||
| 276 | screenPathList.add(csti.rootScreenDef.location) | ||
| 277 | // Add subscreen path segments | ||
| 278 | String[] pathSegments = stri.screenPath.split('/') | ||
| 279 | for (String segment in pathSegments) { | ||
| 280 | if (segment && segment.trim().length() > 0) { | ||
| 281 | screenPathList.add(segment) | ||
| 282 | } | ||
| 283 | } | ||
| 284 | logger.info("Custom screen path parsing for non-webroot root: ${screenPathList}") | ||
| 285 | } else { | ||
| 286 | screenPathList = ScreenUrlInfo.parseSubScreenPath(csti.rootScreenDef, csti.baseScreenDef, | ||
| 268 | csti.baseScreenPathList, stri.screenPath, stri.parameters, csti.sfi) | 287 | csti.baseScreenPathList, stri.screenPath, stri.parameters, csti.sfi) |
| 288 | } | ||
| 269 | if (screenPathList == null) throw new BaseArtifactException("Could not find screen path ${stri.screenPath} under base screen ${csti.baseScreenDef.location}") | 289 | if (screenPathList == null) throw new BaseArtifactException("Could not find screen path ${stri.screenPath} under base screen ${csti.baseScreenDef.location}") |
| 270 | 290 | ||
| 271 | // push the context | 291 | // push the context |
| ... | @@ -292,7 +312,7 @@ class CustomScreenTestImpl implements McpScreenTest { | ... | @@ -292,7 +312,7 @@ class CustomScreenTestImpl implements McpScreenTest { |
| 292 | } | 312 | } |
| 293 | 313 | ||
| 294 | // set the screenPath | 314 | // set the screenPath |
| 295 | screenRender.screenPath(screenPathList) | 315 | screenRender.screenPath(screenPathList as java.util.List<String>) |
| 296 | 316 | ||
| 297 | // do the render | 317 | // do the render |
| 298 | try { | 318 | try { | ... | ... |
| ... | @@ -862,8 +862,13 @@ logger.info("Handling Enhanced SSE connection from ${request.remoteAddr}") | ... | @@ -862,8 +862,13 @@ logger.info("Handling Enhanced SSE connection from ${request.remoteAddr}") |
| 862 | logger.error("Enhanced MCP service ${serviceName} returned null result") | 862 | logger.error("Enhanced MCP service ${serviceName} returned null result") |
| 863 | return [error: "Service returned null result"] | 863 | return [error: "Service returned null result"] |
| 864 | } | 864 | } |
| 865 | // Service framework returns result in 'result' field, but also might return the result directly | 865 | // Service framework returns result in 'result' field when out-parameters are used |
| 866 | return result.result ?: result ?: [error: "Service returned invalid result"] | 866 | // Unwrap the Moqui service result to avoid double nesting in JSON-RPC response |
| 867 | if (result?.containsKey('result')) { | ||
| 868 | return result.result ?: [error: "Service returned empty result"] | ||
| 869 | } else { | ||
| 870 | return result ?: [error: "Service returned null result"] | ||
| 871 | } | ||
| 867 | } catch (Exception e) { | 872 | } catch (Exception e) { |
| 868 | logger.error("Error calling Enhanced MCP service ${serviceName}", e) | 873 | logger.error("Error calling Enhanced MCP service ${serviceName}", e) |
| 869 | return [error: e.message] | 874 | return [error: e.message] | ... | ... |
-
Please register or sign in to post a comment