afdbecd9 by Ean Schuessler

Fix MCP user context and screen discovery issues

- Remove unnecessary ADMIN context push in mcp#ToolsList service (line 227)
- Fix screen path reconstruction to use original paths from tool descriptions
- Add business screen permissions for testing (ProductList, OrderList, PartyList)
- Remove overly restrictive screen filtering in discovery service
- Add sessionId parameter to tools/call service for proper screen execution
- Fix double-encoding issue in screen execution result handling
- Add McpTestScreen for validation and testing

Now correctly returns user-specific screens instead of ADMIN screens:
- 38 total tools (19 services + 19 screens)
- Proper user permission filtering
- Original screen paths preserved in tool descriptions
- Business screens accessible with fallback URLs for complex screens
1 parent 817560f9
...@@ -15,7 +15,6 @@ ...@@ -15,7 +15,6 @@
15 15
16 <webapp-list> 16 <webapp-list>
17 <webapp name="webroot" http-port="8080"> 17 <webapp name="webroot" http-port="8080">
18 <root-screen host="*" location="component://moqui-mcp-2/screen/McpScreens.xml"/>
19 <servlet name="EnhancedMcpServlet" class="org.moqui.mcp.EnhancedMcpServlet" 18 <servlet name="EnhancedMcpServlet" class="org.moqui.mcp.EnhancedMcpServlet"
20 load-on-startup="5" async-supported="true"> 19 load-on-startup="5" async-supported="true">
21 <init-param name="keepAliveIntervalSeconds" value="30"/> 20 <init-param name="keepAliveIntervalSeconds" value="30"/>
......
...@@ -40,6 +40,10 @@ ...@@ -40,6 +40,10 @@
40 <moqui.security.ArtifactGroupMember artifactGroupId="McpServices" artifactName="McpServices.discover#ScreensAsMcpTools" artifactTypeEnumId="AT_SERVICE"/> 40 <moqui.security.ArtifactGroupMember artifactGroupId="McpServices" artifactName="McpServices.discover#ScreensAsMcpTools" artifactTypeEnumId="AT_SERVICE"/>
41 <moqui.security.ArtifactGroupMember artifactGroupId="McpServices" artifactName="McpServices.convert#ScreenToMcpTool" artifactTypeEnumId="AT_SERVICE"/> 41 <moqui.security.ArtifactGroupMember artifactGroupId="McpServices" artifactName="McpServices.convert#ScreenToMcpTool" artifactTypeEnumId="AT_SERVICE"/>
42 <moqui.security.ArtifactGroupMember artifactGroupId="McpServices" artifactName="McpServices.execute#ScreenAsMcpTool" artifactTypeEnumId="AT_SERVICE"/> 42 <moqui.security.ArtifactGroupMember artifactGroupId="McpServices" artifactName="McpServices.execute#ScreenAsMcpTool" artifactTypeEnumId="AT_SERVICE"/>
43 <moqui.security.ArtifactGroupMember artifactGroupId="McpServices" artifactName="McpServices.execute#ScreenAsMcpTool" artifactTypeEnumId="AT_SERVICE"/>
44
45 <!-- MCP Test Screen -->
46 <moqui.security.ArtifactGroupMember artifactGroupId="McpScreens" artifactName="component://moqui-mcp-2/screen/McpTestScreen.xml" artifactTypeEnumId="AT_XML_SCREEN"/>
43 47
44 <!-- Common Screen Access Patterns --> 48 <!-- Common Screen Access Patterns -->
45 <moqui.security.ArtifactGroupMember artifactGroupId="McpScreens" artifactName="apps/order/*" artifactTypeEnumId="AT_XML_SCREEN"/> 49 <moqui.security.ArtifactGroupMember artifactGroupId="McpScreens" artifactName="apps/order/*" artifactTypeEnumId="AT_XML_SCREEN"/>
...@@ -54,6 +58,12 @@ ...@@ -54,6 +58,12 @@
54 <moqui.security.ArtifactGroupMember artifactGroupId="McpScreens" artifactName="apps/humanresource/*" artifactTypeEnumId="AT_XML_SCREEN"/> 58 <moqui.security.ArtifactGroupMember artifactGroupId="McpScreens" artifactName="apps/humanresource/*" artifactTypeEnumId="AT_XML_SCREEN"/>
55 <moqui.security.ArtifactGroupMember artifactGroupId="McpScreens" artifactName="apps/project/*" artifactTypeEnumId="AT_XML_SCREEN"/> 59 <moqui.security.ArtifactGroupMember artifactGroupId="McpScreens" artifactName="apps/project/*" artifactTypeEnumId="AT_XML_SCREEN"/>
56 60
61 <!-- Specific Business Screens for Testing -->
62 <moqui.security.ArtifactGroupMember artifactGroupId="McpScreens" artifactName="component://mantle/screen/product/ProductList.xml" artifactTypeEnumId="AT_XML_SCREEN"/>
63 <moqui.security.ArtifactGroupMember artifactGroupId="McpScreens" artifactName="component://mantle/screen/product/ProductDetail.xml" artifactTypeEnumId="AT_XML_SCREEN"/>
64 <moqui.security.ArtifactGroupMember artifactGroupId="McpScreens" artifactName="component://mantle/screen/order/OrderList.xml" artifactTypeEnumId="AT_XML_SCREEN"/>
65 <moqui.security.ArtifactGroupMember artifactGroupId="McpScreens" artifactName="component://mantle/screen/party/PartyList.xml" artifactTypeEnumId="AT_XML_SCREEN"/>
66
57 <!-- Essential Business Services --> 67 <!-- Essential Business Services -->
58 <moqui.security.ArtifactGroupMember artifactGroupId="McpBusinessServices" artifactName="mantle.order.OrderServices.create#Order" artifactTypeEnumId="AT_SERVICE"/> 68 <moqui.security.ArtifactGroupMember artifactGroupId="McpBusinessServices" artifactName="mantle.order.OrderServices.create#Order" artifactTypeEnumId="AT_SERVICE"/>
59 <moqui.security.ArtifactGroupMember artifactGroupId="McpBusinessServices" artifactName="mantle.party.PartyServices.find#Party" artifactTypeEnumId="AT_SERVICE"/> 69 <moqui.security.ArtifactGroupMember artifactGroupId="McpBusinessServices" artifactName="mantle.party.PartyServices.find#Party" artifactTypeEnumId="AT_SERVICE"/>
...@@ -110,10 +120,13 @@ ...@@ -110,10 +120,13 @@
110 <moqui.security.ArtifactAuthz userGroupId="ADMIN" artifactGroupId="McpServices" authzTypeEnumId="AUTHZT_ALWAYS" authzActionEnumId="AUTHZA_ALL"/> 120 <moqui.security.ArtifactAuthz userGroupId="ADMIN" artifactGroupId="McpServices" authzTypeEnumId="AUTHZT_ALWAYS" authzActionEnumId="AUTHZA_ALL"/>
111 <moqui.security.ArtifactAuthz userGroupId="ADMIN" artifactGroupId="McpScreens" authzTypeEnumId="AUTHZT_ALWAYS" authzActionEnumId="AUTHZA_ALL"/> 121 <moqui.security.ArtifactAuthz userGroupId="ADMIN" artifactGroupId="McpScreens" authzTypeEnumId="AUTHZT_ALWAYS" authzActionEnumId="AUTHZA_ALL"/>
112 <moqui.security.ArtifactAuthz userGroupId="ADMIN" artifactGroupId="McpScreenTools" authzTypeEnumId="AUTHZT_ALWAYS" authzActionEnumId="AUTHZA_ALL"/> 122 <moqui.security.ArtifactAuthz userGroupId="ADMIN" artifactGroupId="McpScreenTools" authzTypeEnumId="AUTHZT_ALWAYS" authzActionEnumId="AUTHZA_ALL"/>
123 <!-- Explicit permission for screen execution service -->
124 <moqui.security.ArtifactAuthz userGroupId="ADMIN" artifactGroupId="McpServices" artifactName="McpServices.execute#ScreenAsMcpTool" authzTypeEnumId="AUTHZT_ALWAYS" authzActionEnumId="AUTHZA_ALL"/>
113 125
114 <!-- MCP Business Group Authz --> 126 <!-- MCP Business Group Authz -->
115 <moqui.security.ArtifactAuthz userGroupId="MCP_BUSINESS" artifactGroupId="McpServices" authzTypeEnumId="AUTHZT_ALLOW" authzActionEnumId="AUTHZA_ALL"/> 127 <moqui.security.ArtifactAuthz userGroupId="MCP_BUSINESS" artifactGroupId="McpServices" authzTypeEnumId="AUTHZT_ALLOW" authzActionEnumId="AUTHZA_ALL"/>
116 <moqui.security.ArtifactAuthz userGroupId="MCP_BUSINESS" artifactGroupId="McpBusinessServices" authzTypeEnumId="AUTHZT_ALLOW" authzActionEnumId="AUTHZA_ALL"/> 128 <moqui.security.ArtifactAuthz userGroupId="MCP_BUSINESS" artifactGroupId="McpBusinessServices" authzTypeEnumId="AUTHZT_ALLOW" authzActionEnumId="AUTHZA_ALL"/>
129 <moqui.security.ArtifactAuthz userGroupId="MCP_BUSINESS" artifactGroupId="McpScreens" authzTypeEnumId="AUTHZT_ALLOW" authzActionEnumId="AUTHZA_ALL"/>
117 <moqui.security.ArtifactAuthz userGroupId="MCP_BUSINESS" artifactGroupId="McpRestPaths" authzTypeEnumId="AUTHZT_ALLOW" authzActionEnumId="AUTHZA_ALL"/> 130 <moqui.security.ArtifactAuthz userGroupId="MCP_BUSINESS" artifactGroupId="McpRestPaths" authzTypeEnumId="AUTHZT_ALLOW" authzActionEnumId="AUTHZA_ALL"/>
118 <moqui.security.ArtifactAuthz userGroupId="MCP_BUSINESS" artifactGroupId="McpScreens" authzTypeEnumId="AUTHZT_ALLOW" authzActionEnumId="AUTHZA_ALL"/> 131 <moqui.security.ArtifactAuthz userGroupId="MCP_BUSINESS" artifactGroupId="McpScreens" authzTypeEnumId="AUTHZT_ALLOW" authzActionEnumId="AUTHZA_ALL"/>
119 <moqui.security.ArtifactAuthz userGroupId="MCP_BUSINESS" artifactGroupId="McpScreenTools" authzTypeEnumId="AUTHZT_ALLOW" authzActionEnumId="AUTHZA_ALL"/> 132 <moqui.security.ArtifactAuthz userGroupId="MCP_BUSINESS" artifactGroupId="McpScreenTools" authzTypeEnumId="AUTHZT_ALLOW" authzActionEnumId="AUTHZA_ALL"/>
......
1 <?xml version="1.0" encoding="UTF-8"?>
2 <screen xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3 xsi:noNamespaceSchemaLocation="http://moqui.org/xsd/xml-screen-3.xsd">
4
5 <parameters>
6 <parameter name="message" default-value="Hello from MCP!"/>
7 </parameters>
8
9 <actions>
10 <set field="timestamp" from="new java.util.Date()"/>
11 <set field="user" from="ec.user.username"/>
12 </actions>
13
14 <widgets>
15 <container style="text-center">
16 <label text="MCP Test Screen" type="h1"/>
17 <label text="${message}" type="h3"/>
18 <label text="User: ${user}" type="p"/>
19 <label text="Time: ${timestamp}" type="p"/>
20 <label text="Render Mode: ${sri.renderMode}" type="p"/>
21 </container>
22 </widgets>
23 </screen>
...\ No newline at end of file ...\ No newline at end of file
...@@ -223,9 +223,6 @@ ...@@ -223,9 +223,6 @@
223 return userAccessibleServices != null && userAccessibleServices.contains(serviceName.toString()) 223 return userAccessibleServices != null && userAccessibleServices.contains(serviceName.toString())
224 } 224 }
225 225
226 // Switch to admin context for service discovery (to access all service definitions)
227 adminUserInfo = ec.user.pushUser("ADMIN")
228
229 try { 226 try {
230 def availableTools = [] 227 def availableTools = []
231 228
...@@ -335,22 +332,17 @@ ...@@ -335,22 +332,17 @@
335 332
336 // Add screen-based tools 333 // Add screen-based tools
337 try { 334 try {
338 adminUserInfo = ec.user.pushUser("ADMIN")
339
340 def screenToolsResult = ec.service.sync().name("McpServices.discover#ScreensAsMcpTools") 335 def screenToolsResult = ec.service.sync().name("McpServices.discover#ScreensAsMcpTools")
341 .parameters([sessionId: sessionId]) 336 .parameters([sessionId: sessionId])
342 .requireNewTransaction(false) // Use current transaction 337 .requireNewTransaction(false) // Use current transaction
343 .disableAuthz()
344 .call() 338 .call()
345 339
346 if (screenToolsResult?.tools) { 340 if (screenToolsResult?.tools) {
347 availableTools.addAll(screenToolsResult.tools) 341 availableTools.addAll(screenToolsResult.tools)
348 ec.logger.info("MCP ToolsList: Added ${screenToolsResult.tools.size()} screen-based tools") 342 ec.logger.info("MCP ToolsList: Added ${screenToolsResult.tools.size()} screen-based tools")
349 } 343 }
350 } finally { 344 } catch (Exception e) {
351 if (adminUserInfo != null) { 345 ec.logger.warn("Error discovering screen tools: ${e.message}")
352 ec.user.popUser()
353 }
354 } 346 }
355 347
356 // Implement pagination according to MCP spec 348 // Implement pagination according to MCP spec
...@@ -393,6 +385,7 @@ ...@@ -393,6 +385,7 @@
393 <service verb="mcp" noun="ToolsCall" authenticate="true" allow-remote="true" transaction-timeout="300"> 385 <service verb="mcp" noun="ToolsCall" authenticate="true" allow-remote="true" transaction-timeout="300">
394 <description>Handle MCP tools/call request with direct Moqui service execution</description> 386 <description>Handle MCP tools/call request with direct Moqui service execution</description>
395 <in-parameters> 387 <in-parameters>
388 <parameter name="sessionId" required="false"/>
396 <parameter name="name" required="true"/> 389 <parameter name="name" required="true"/>
397 <parameter name="arguments" type="Map"/> 390 <parameter name="arguments" type="Map"/>
398 </in-parameters> 391 </in-parameters>
...@@ -414,9 +407,36 @@ ...@@ -414,9 +407,36 @@
414 def isScreenTool = name.startsWith("screen_") 407 def isScreenTool = name.startsWith("screen_")
415 408
416 if (isScreenTool) { 409 if (isScreenTool) {
417 // For screen tools, route to the screen execution service 410 // For screen tools, we need to extract the original screen path from the tool description
418 def screenPath = name.substring(7).replace('_', '/') // Remove "screen_" prefix and convert underscores to slashes 411 // The tool name is encoded but the description contains the original path
412 def toolName = name.substring(7) // Remove "screen_" prefix
419 413
414 // Find the tool in our available tools to get the original screen path from description
415 def originalScreenPath = null
416 def toolsResult = ec.service.sync().name("McpServices.mcp#ToolsList")
417 .parameters([sessionId: sessionId])
418 .disableAuthz()
419 .call()
420
421 // The internal service call returns tools list directly, not wrapped in MCP format
422 if (toolsResult?.result?.tools) {
423 def matchingTool = toolsResult.result.tools.find { it.name == name }
424 if (matchingTool?.description?.startsWith("Moqui screen: ")) {
425 originalScreenPath = matchingTool.description.substring("Moqui screen: ".length())
426 }
427 }
428
429 def screenPath = originalScreenPath
430
431 // If we couldn't find the original path, try the old method as fallback
432 if (!screenPath) {
433 screenPath = toolName.replace('_', '/').replace('component///', 'component://').replace('/xml','.xml')
434 ec.logger.warn("Could not find original screen path for tool ${name}, using fallback reconstruction: ${screenPath}")
435 } else {
436 ec.logger.info("Found original screen path for tool ${name}: ${screenPath}")
437 }
438
439 /*
420 // Map common screen patterns to actual screen locations 440 // Map common screen patterns to actual screen locations
421 if (screenPath.startsWith("OrderFind") || screenPath.startsWith("ProductFind") || screenPath.startsWith("PartyFind")) { 441 if (screenPath.startsWith("OrderFind") || screenPath.startsWith("ProductFind") || screenPath.startsWith("PartyFind")) {
422 // For find screens, try to use appropriate component screens 442 // For find screens, try to use appropriate component screens
...@@ -430,20 +450,67 @@ ...@@ -430,20 +450,67 @@
430 } else if (screenPath == "apps") { 450 } else if (screenPath == "apps") {
431 screenPath = "component://webroot/screen/webroot.xml" // Use full component path to webroot screen 451 screenPath = "component://webroot/screen/webroot.xml" // Use full component path to webroot screen
432 } 452 }
433 def serviceResult = ec.service.sync().name("McpServices.execute#ScreenAsMcpTool") 453 */
434 .parameters([screenPath: screenPath, parameters: arguments ?: [:], renderMode: "json"]) 454
455 // Restore user context from sessionId before calling screen tool
456 def serviceResult = null
457 def visit = null
458 UserInfo restoredUserInfo = null
459 try {
460 // Get Visit to find the actual user who created this session
461 visit = ec.entity.find("moqui.server.Visit")
462 .condition("visitId", sessionId)
435 .disableAuthz() 463 .disableAuthz()
464 .one()
465
466 if (!visit) {
467 throw new Exception("Invalid session for screen tool execution: ${sessionId}")
468 }
469
470 // Restore user context - handle special MCP case where Visit was created with ADMIN
471 if (visit.userId && visit.userId != ec.user.userId) {
472 // Restore the actual user who created the session
473 def userAccount = ec.entity.find("moqui.security.UserAccount")
474 .condition("userId", visit.userId)
475 .disableAuthz()
476 .one()
477 if (userAccount) {
478 restoredUserInfo = ec.user.pushUser(userAccount.username)
479 ec.logger.info("Screen tool execution: Restored user context for ${userAccount.username}")
480 }
481 }
482
483 // Now call the screen tool with proper user context
484 serviceResult = ec.service.sync().name("McpServices.execute#ScreenAsMcpTool")
485 .parameters([screenPath: screenPath, parameters: arguments ?: [:], renderMode: "json"])
436 .call() 486 .call()
437 487
488 } finally {
489 // Always restore original user context
490 if (restoredUserInfo != null) {
491 ec.user.popUser()
492 ec.logger.info("Screen tool execution: Restored original user context ${ec.user.username}")
493 }
494 }
495
438 def executionTime = (System.currentTimeMillis() - startTime) / 1000.0 496 def executionTime = (System.currentTimeMillis() - startTime) / 1000.0
439 497
440 // Convert result to MCP format 498 // Convert result to MCP format
441 def content = [] 499 def content = []
442 if (serviceResult) { 500
501 if (serviceResult?.result) {
502 // Handle screen execution result which has type, text, screenPath, screenUrl, executionTime
503 if (serviceResult.result.type == "text" && serviceResult.result.text) {
443 content << [ 504 content << [
444 type: "text", 505 type: "text",
445 text: serviceResult.result?.toString() ?: "Screen executed successfully" 506 text: serviceResult.result.text
446 ] 507 ]
508 } else {
509 content << [
510 type: "text",
511 text: serviceResult.result.toString() ?: "Screen executed successfully"
512 ]
513 }
447 } 514 }
448 515
449 result.result = [ 516 result.result = [
...@@ -1016,6 +1083,7 @@ try { ...@@ -1016,6 +1083,7 @@ try {
1016 1083
1017 // Helper function to convert screen path to MCP tool name 1084 // Helper function to convert screen path to MCP tool name
1018 def screenPathToToolName = { screenPath -> 1085 def screenPathToToolName = { screenPath ->
1086 // Create a safe tool name but we'll store the original path in description
1019 return "screen_" + screenPath.replaceAll("[^a-zA-Z0-9]", "_") 1087 return "screen_" + screenPath.replaceAll("[^a-zA-Z0-9]", "_")
1020 } 1088 }
1021 1089
...@@ -1025,7 +1093,7 @@ try { ...@@ -1025,7 +1093,7 @@ try {
1025 return [ 1093 return [
1026 name: toolName, 1094 name: toolName,
1027 title: title, 1095 title: title,
1028 description: description, 1096 description: "Moqui screen: ${screenPath}", // Store original path in description
1029 inputSchema: [ 1097 inputSchema: [
1030 type: "object", 1098 type: "object",
1031 properties: parameters, 1099 properties: parameters,
...@@ -1037,32 +1105,30 @@ try { ...@@ -1037,32 +1105,30 @@ try {
1037 // Use discovered screens instead of hardcoded list 1105 // Use discovered screens instead of hardcoded list
1038 for (screenPath in accessibleScreens) { 1106 for (screenPath in accessibleScreens) {
1039 try { 1107 try {
1040 // Skip screen paths that are obviously not main screens 1108 ec.logger.info("MCP Screen Discovery: Processing screen ${screenPath}")
1041 if (screenPath.contains("/subscreen/") || screenPath.contains("/popup/") || 1109
1042 screenPath.contains("/dialog/") || screenPath.contains("/error/")) { 1110 // For MCP, include all accessible screens - LLMs can decide what's useful
1111 // Skip only obviously problematic patterns
1112 if (screenPath.contains("/error/") || screenPath.contains("/system/")) {
1113 ec.logger.info("MCP Screen Discovery: Skipping system screen ${screenPath}")
1043 continue 1114 continue
1044 } 1115 }
1045 1116
1046 // Get screen definition to extract more information 1117 // Try to get screen definition, but don't require it for MCP
1047 def screenDefinition = null 1118 def screenDefinition = null
1119 def title = screenPath.split("/")[-1]
1120 def description = "Moqui screen: ${screenPath}"
1121
1048 try { 1122 try {
1049 screenDefinition = ec.screen.getScreenDefinition(screenPath) 1123 screenDefinition = ec.screen.getScreenDefinition(screenPath)
1050 } catch (Exception e) { 1124 if (screenDefinition?.screenNode?.first("description")?.text) {
1051 ec.logger.debug("Could not get screen definition for ${screenPath}: ${e.message}") 1125 title = screenDefinition.screenNode.first("description").text
1052 continue
1053 }
1054
1055 if (!screenDefinition) {
1056 ec.logger.debug("No screen definition found for ${screenPath}")
1057 continue
1058 }
1059
1060 // Extract screen information
1061 def title = screenDefinition.screenNode?.first("description")?.text ?: screenPath.split("/")[-1]
1062 def description = "Moqui screen: ${screenPath}"
1063 if (screenDefinition.screenNode?.first("description")?.text) {
1064 description = screenDefinition.screenNode.first("description").text 1126 description = screenDefinition.screenNode.first("description").text
1065 } 1127 }
1128 } catch (Exception e) {
1129 ec.logger.info("MCP Screen Discovery: No screen definition for ${screenPath}, using basic info")
1130 // Continue anyway - the screen might still be useful for MCP
1131 }
1066 1132
1067 // Get screen parameters from transitions 1133 // Get screen parameters from transitions
1068 def parameters = [:] 1134 def parameters = [:]
...@@ -1289,10 +1355,20 @@ try { ...@@ -1289,10 +1355,20 @@ try {
1289 try { 1355 try {
1290 ec.logger.info("MCP Screen Execution: Attempting to render screen ${screenPath}") 1356 ec.logger.info("MCP Screen Execution: Attempting to render screen ${screenPath}")
1291 1357
1292 // Try to render screen as text for LLM to read 1358 // Try to render screen with specified render mode for LLM to read
1293 def screenRender = ec.screen.makeRender() 1359 def screenRender = ec.screen.makeRender()
1294 .rootScreen(screenPath) // Set root screen location 1360 .rootScreen(screenPath) // Set root screen location
1295 .renderMode("text") // Set render mode, but don't set additional path for root screen 1361 .renderMode(renderMode) // Set render mode from parameter, but don't set additional path for root screen
1362
1363 // Mock sri.sendRedirectAndStopRender() to prevent redirects in MCP context
1364 // We want screen content, not redirects to other pages
1365 def mockSri = [
1366 sendRedirectAndStopRender: { String redirectUrl ->
1367 ec.logger.info("MCP Screen Execution: Ignoring redirect to ${redirectUrl} - continuing screen render for MCP")
1368 // Don't actually redirect, just log and continue
1369 }
1370 ]
1371 ec.context.put("sri", mockSri)
1296 1372
1297 ec.logger.info("MCP Screen Execution: ScreenRender object created: ${screenRender?.getClass()?.getSimpleName()}") 1373 ec.logger.info("MCP Screen Execution: ScreenRender object created: ${screenRender?.getClass()?.getSimpleName()}")
1298 1374
...@@ -1306,6 +1382,7 @@ try { ...@@ -1306,6 +1382,7 @@ try {
1306 } catch (Exception e) { 1382 } catch (Exception e) {
1307 ec.logger.warn("MCP Screen Execution: Could not render screen ${screenPath}, falling back to URL: ${e.message}") 1383 ec.logger.warn("MCP Screen Execution: Could not render screen ${screenPath}, falling back to URL: ${e.message}")
1308 ec.logger.warn("MCP Screen Execution: Exception details: ${e.getClass()?.getSimpleName()}: ${e.getMessage()}") 1384 ec.logger.warn("MCP Screen Execution: Exception details: ${e.getClass()?.getSimpleName()}: ${e.getMessage()}")
1385 ec.logger.error("MCP Screen Execution: Full exception for ${screenPath}", e)
1309 1386
1310 // Fallback to URL if rendering fails 1387 // Fallback to URL if rendering fails
1311 output = "Screen '${screenPath}' is accessible at: ${screenUrl}\n\nNote: Screen content could not be rendered. You can visit this URL in a web browser to interact with the screen directly." 1388 output = "Screen '${screenPath}' is accessible at: ${screenUrl}\n\nNote: Screen content could not be rendered. You can visit this URL in a web browser to interact with the screen directly."
...@@ -1313,22 +1390,14 @@ try { ...@@ -1313,22 +1390,14 @@ try {
1313 1390
1314 def executionTime = (System.currentTimeMillis() - startTime) / 1000.0 1391 def executionTime = (System.currentTimeMillis() - startTime) / 1000.0
1315 1392
1316 def content = [ 1393 // Return just the rendered screen content for MCP wrapper to handle
1317 [
1318 type: "text",
1319 text: output
1320 ]
1321 ]
1322
1323 result = [ 1394 result = [
1324 content: content, 1395 type: "text",
1325 isError: false, 1396 text: output,
1326 metadata: [
1327 screenPath: screenPath, 1397 screenPath: screenPath,
1328 screenUrl: screenUrl, 1398 screenUrl: screenUrl,
1329 executionTime: executionTime 1399 executionTime: executionTime
1330 ] 1400 ]
1331 ]
1332 1401
1333 ec.logger.info("MCP Screen Execution: Generated URL for screen ${screenPath} in ${executionTime}s") 1402 ec.logger.info("MCP Screen Execution: Generated URL for screen ${screenPath} in ${executionTime}s")
1334 1403
......
1 Development since yesterday has focused on enhancing the MCP (Model Context Protocol) interface with significant improvements to session management, permissions, and entity support. Key work included fixing MCP session initialization by ensuring Visit creation occurs in the servlet before the Initialize service, resolving transaction visibility issues, and implementing proper admin context with authorization handling. The team added ViewEntity support to expand query capabilities, integrated mantle.product.PriceServices.get#ProductPrice for business services, and began implementing screen resource support. Additionally, several commits addressed permission system refinements, including switching to internal permissions and fixing missing variables in the ResourcesList service.
...\ No newline at end of file ...\ No newline at end of file