b54f0e3c by Ean Schuessler

Use real web sessions for action execution

Remove mock/test session requirement when action != null
This allows database updates to persist when action is executed through MCP.
1 parent 0fc4e236
...@@ -606,7 +606,8 @@ ...@@ -606,7 +606,8 @@
606 <description>Execute a screen as an MCP tool</description> 606 <description>Execute a screen as an MCP tool</description>
607 <in-parameters> 607 <in-parameters>
608 <parameter name="screenPath" required="true"/> 608 <parameter name="screenPath" required="true"/>
609 <parameter name="parameters" type="Map"><description>Parameters to pass to the screen</description></parameter> 609 <parameter name="parameters" type="Map"><description>Parameters to pass to screen</description></parameter>
610 <parameter name="action"><description>Action being processed: if not null, use real screen rendering instead of test mock</description></parameter>
610 <parameter name="renderMode" default="mcp"><description>Render mode: mcp, text, html, xml, vuet, qvt</description></parameter> 611 <parameter name="renderMode" default="mcp"><description>Render mode: mcp, text, html, xml, vuet, qvt</description></parameter>
611 <parameter name="sessionId"><description>Session ID for user context restoration</description></parameter> 612 <parameter name="sessionId"><description>Session ID for user context restoration</description></parameter>
612 <parameter name="subscreenName"><description>Optional subscreen name for dot notation paths</description></parameter> 613 <parameter name="subscreenName"><description>Optional subscreen name for dot notation paths</description></parameter>
...@@ -628,15 +629,18 @@ def startTime = System.currentTimeMillis() ...@@ -628,15 +629,18 @@ def startTime = System.currentTimeMillis()
628 ec.context.putAll(parameters) 629 ec.context.putAll(parameters)
629 } 630 }
630 631
632 // Check if action is being processed - use real screen rendering if so
633 def isActionExecution = parameters?.action != null
634
631 // Try to render screen content for LLM consumption 635 // Try to render screen content for LLM consumption
632 def output = null 636 def output = null
633 def screenUrl = "http://localhost:8080/${screenPath}" 637 def screenUrl = "http://localhost:8080/${screenPath}"
634 def isError = false 638 def isError = false
635 639
636 try { 640 try {
637 ec.logger.info("MCP Screen Execution: Attempting to render screen ${screenPath} using ScreenTest with proper root screen") 641 ec.logger.info("MCP Screen Execution: Attempting to render screen ${screenPath} using ScreenTest with proper root screen, action=${parameters?.action}")
638 642
639 // For ScreenTest to work properly, we need to use the correct root screen 643 // For ScreenTest to work properly, we need to use correct root screen
640 def testScreenPath = screenPath 644 def testScreenPath = screenPath
641 def rootScreen = "component://webroot/screen/webroot.xml" 645 def rootScreen = "component://webroot/screen/webroot.xml"
642 646
...@@ -647,7 +651,7 @@ def startTime = System.currentTimeMillis() ...@@ -647,7 +651,7 @@ def startTime = System.currentTimeMillis()
647 def pathAfterComponent = screenPath.substring(12).replace('.xml','') // Remove "component://" 651 def pathAfterComponent = screenPath.substring(12).replace('.xml','') // Remove "component://"
648 def pathParts = pathAfterComponent.split("/") 652 def pathParts = pathAfterComponent.split("/")
649 653
650 // Check if the target screen itself is standalone 654 // Check if target screen itself is standalone
651 try { 655 try {
652 targetScreenDef = ec.screen.getScreenDefinition(screenPath) 656 targetScreenDef = ec.screen.getScreenDefinition(screenPath)
653 if (targetScreenDef?.screenNode) { 657 if (targetScreenDef?.screenNode) {
...@@ -664,7 +668,7 @@ def startTime = System.currentTimeMillis() ...@@ -664,7 +668,7 @@ def startTime = System.currentTimeMillis()
664 } 668 }
665 669
666 if (!isStandalone) { 670 if (!isStandalone) {
667 // Check if the screen path itself is a valid screen definition 671 // Check if screen path itself is a valid screen definition
668 try { 672 try {
669 if (ec.screen.getScreenDefinition(screenPath)) { 673 if (ec.screen.getScreenDefinition(screenPath)) {
670 rootScreen = screenPath 674 rootScreen = screenPath
...@@ -678,42 +682,42 @@ def startTime = System.currentTimeMillis() ...@@ -678,42 +682,42 @@ def startTime = System.currentTimeMillis()
678 testScreenPath = testScreenPath.substring("webroot/".length()) 682 testScreenPath = testScreenPath.substring("webroot/".length())
679 } 683 }
680 } else { 684 } else {
681 def componentName = pathParts[0]
682 def remainingPath = pathParts[1..-1].join("/")
683
684 // Try to find the actual root screen for this component
685 def componentRootScreen = null
686 def possibleRootScreens = ["${componentName}.xml", "${componentName}Admin.xml", "${componentName}Root.xml"]
687
688 for (rootScreenName in possibleRootScreens) {
689 def candidateRoot = "component://${componentName}/screen/${rootScreenName}"
690 try {
691 if (ec.screen.getScreenDefinition(candidateRoot)) {
692 componentRootScreen = candidateRoot
693 break
694 }
695 } catch (Exception e) {}
696 }
697
698 if (componentRootScreen) {
699 rootScreen = componentRootScreen
700 testScreenPath = remainingPath
701 } else {
702 rootScreen = screenPath 685 rootScreen = screenPath
703 testScreenPath = "" 686 testScreenPath = ""
704 } 687 }
705 } 688 }
689 } catch (Exception e) {}
706 } 690 }
707 } catch (Exception e) { 691
708 // Same as above fallback 692 } else {
709 rootScreen = screenPath 693 rootScreen = screenPath
710 testScreenPath = "" 694 testScreenPath = ""
711 } 695 }
712 }
713 }
714 696
715 // Regular screen rendering with current user context - use our custom ScreenTestImpl 697 // Regular screen rendering with current user context - use real rendering if action is being processed
716 def screenTest = new org.moqui.mcp.CustomScreenTestImpl(ec.ecfi) 698 def screenTest = null
699 def screenUrl = "http://localhost:8080/${screenPath}"
700
701 if (isActionExecution) {
702 // Action is being processed - use real screen rendering with database access
703 ec.logger.info("MCP Screen Execution: Action detected, using real screen rendering for ${screenPath}")
704 screenTest = ec.screen.makeTestScreen()
705 .rootScreen(rootScreen)
706 .renderMode(renderMode ? renderMode : "mcp")
707 .auth(ec.user.username)
708
709 def renderParams = parameters ?: [:]
710 renderParams.userId = ec.user.userId
711 renderParams.username = ec.user.username
712
713 def relativePath = subscreenName ? subscreenName.replaceAll('_','/') : testScreenPath
714 ec.logger.info("REALRENDER root=${rootScreen} path=${relativePath} params=${renderParams}")
715
716 def realRender = screenTest.render(relativePath, renderParams, "POST")
717 } else {
718 // Regular browse - use ScreenTest mock
719 ec.logger.info("MCP Screen Execution: No action detected, using ScreenTest mock")
720 screenTest = new org.moqui.mcp.CustomScreenTestImpl(ec.ecfi)
717 .rootScreen(rootScreen) 721 .rootScreen(rootScreen)
718 .renderMode(renderMode ? renderMode : "mcp") 722 .renderMode(renderMode ? renderMode : "mcp")
719 .auth(ec.user.username) 723 .auth(ec.user.username)
......