f4695781 by Ean Schuessler

start adding screen resource support

1 parent 1d9ca524
...@@ -23,6 +23,8 @@ ...@@ -23,6 +23,8 @@
23 <moqui.security.ArtifactGroup artifactGroupId="McpScreenTransitions" description="MCP Screen Transitions"/> 23 <moqui.security.ArtifactGroup artifactGroupId="McpScreenTransitions" description="MCP Screen Transitions"/>
24 <moqui.security.ArtifactGroup artifactGroupId="McpBusinessServices" description="MCP Essential Business Services"/> 24 <moqui.security.ArtifactGroup artifactGroupId="McpBusinessServices" description="MCP Essential Business Services"/>
25 <moqui.security.ArtifactGroup artifactGroupId="McpSecurityEntities" description="Security entities needed for permission checks"/> 25 <moqui.security.ArtifactGroup artifactGroupId="McpSecurityEntities" description="Security entities needed for permission checks"/>
26 <moqui.security.ArtifactGroup artifactGroupId="McpScreens" description="MCP Screen Access"/>
27 <moqui.security.ArtifactGroup artifactGroupId="McpScreenTools" description="MCP Screen-based Tools"/>
26 28
27 <!-- MCP Artifact Group Members --> 29 <!-- MCP Artifact Group Members -->
28 <moqui.security.ArtifactGroupMember artifactGroupId="McpServices" artifactName="McpServices.*" artifactTypeEnumId="AT_SERVICE"/> 30 <moqui.security.ArtifactGroupMember artifactGroupId="McpServices" artifactName="McpServices.*" artifactTypeEnumId="AT_SERVICE"/>
...@@ -34,6 +36,24 @@ ...@@ -34,6 +36,24 @@
34 <moqui.security.ArtifactGroupMember artifactGroupId="McpServices" artifactName="McpServices.mcp#ResourcesList" artifactTypeEnumId="AT_SERVICE"/> 36 <moqui.security.ArtifactGroupMember artifactGroupId="McpServices" artifactName="McpServices.mcp#ResourcesList" artifactTypeEnumId="AT_SERVICE"/>
35 <moqui.security.ArtifactGroupMember artifactGroupId="McpServices" artifactName="McpServices.mcp#ResourcesRead" artifactTypeEnumId="AT_SERVICE"/> 37 <moqui.security.ArtifactGroupMember artifactGroupId="McpServices" artifactName="McpServices.mcp#ResourcesRead" artifactTypeEnumId="AT_SERVICE"/>
36 38
39 <!-- Screen Discovery and Execution Services -->
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"/>
42 <moqui.security.ArtifactGroupMember artifactGroupId="McpServices" artifactName="McpServices.execute#ScreenAsMcpTool" artifactTypeEnumId="AT_SERVICE"/>
43
44 <!-- Common Screen Access Patterns -->
45 <moqui.security.ArtifactGroupMember artifactGroupId="McpScreens" artifactName="apps/order/*" artifactTypeEnumId="AT_XML_SCREEN"/>
46 <moqui.security.ArtifactGroupMember artifactGroupId="McpScreens" artifactName="apps/party/*" artifactTypeEnumId="AT_XML_SCREEN"/>
47 <moqui.security.ArtifactGroupMember artifactGroupId="McpScreens" artifactName="apps/invoice/*" artifactTypeEnumId="AT_XML_SCREEN"/>
48 <moqui.security.ArtifactGroupMember artifactGroupId="McpScreens" artifactName="apps/product/*" artifactTypeEnumId="AT_XML_SCREEN"/>
49 <moqui.security.ArtifactGroupMember artifactGroupId="McpScreens" artifactName="apps/ledger/*" artifactTypeEnumId="AT_XML_SCREEN"/>
50 <moqui.security.ArtifactGroupMember artifactGroupId="McpScreens" artifactName="apps/marketing/*" artifactTypeEnumId="AT_XML_SCREEN"/>
51 <moqui.security.ArtifactGroupMember artifactGroupId="McpScreens" artifactName="apps/sales/*" artifactTypeEnumId="AT_XML_SCREEN"/>
52 <moqui.security.ArtifactGroupMember artifactGroupId="McpScreens" artifactName="apps/manufacturing/*" artifactTypeEnumId="AT_XML_SCREEN"/>
53 <moqui.security.ArtifactGroupMember artifactGroupId="McpScreens" artifactName="apps/warehouse/*" artifactTypeEnumId="AT_XML_SCREEN"/>
54 <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"/>
56
37 <!-- Essential Business Services --> 57 <!-- Essential Business Services -->
38 <moqui.security.ArtifactGroupMember artifactGroupId="McpBusinessServices" artifactName="mantle.order.OrderServices.create#Order" artifactTypeEnumId="AT_SERVICE"/> 58 <moqui.security.ArtifactGroupMember artifactGroupId="McpBusinessServices" artifactName="mantle.order.OrderServices.create#Order" artifactTypeEnumId="AT_SERVICE"/>
39 <moqui.security.ArtifactGroupMember artifactGroupId="McpBusinessServices" artifactName="mantle.party.PartyServices.find#Party" artifactTypeEnumId="AT_SERVICE"/> 59 <moqui.security.ArtifactGroupMember artifactGroupId="McpBusinessServices" artifactName="mantle.party.PartyServices.find#Party" artifactTypeEnumId="AT_SERVICE"/>
...@@ -80,17 +100,23 @@ ...@@ -80,17 +100,23 @@
80 <moqui.security.ArtifactAuthz userGroupId="McpUser" artifactGroupId="McpServices" authzTypeEnumId="AUTHZT_ALLOW" authzActionEnumId="AUTHZA_ALL"/> 100 <moqui.security.ArtifactAuthz userGroupId="McpUser" artifactGroupId="McpServices" authzTypeEnumId="AUTHZT_ALLOW" authzActionEnumId="AUTHZA_ALL"/>
81 <moqui.security.ArtifactAuthz userGroupId="McpUser" artifactGroupId="McpRestPaths" authzTypeEnumId="AUTHZT_ALLOW" authzActionEnumId="AUTHZA_ALL"/> 101 <moqui.security.ArtifactAuthz userGroupId="McpUser" artifactGroupId="McpRestPaths" authzTypeEnumId="AUTHZT_ALLOW" authzActionEnumId="AUTHZA_ALL"/>
82 <moqui.security.ArtifactAuthz userGroupId="McpUser" artifactGroupId="McpScreenTransitions" authzTypeEnumId="AUTHZT_ALLOW" authzActionEnumId="AUTHZA_ALL"/> 102 <moqui.security.ArtifactAuthz userGroupId="McpUser" artifactGroupId="McpScreenTransitions" authzTypeEnumId="AUTHZT_ALLOW" authzActionEnumId="AUTHZA_ALL"/>
103 <moqui.security.ArtifactAuthz userGroupId="McpUser" artifactGroupId="McpScreens" authzTypeEnumId="AUTHZT_ALLOW" authzActionEnumId="AUTHZA_VIEW"/>
104 <moqui.security.ArtifactAuthz userGroupId="McpUser" artifactGroupId="McpScreenTools" authzTypeEnumId="AUTHZT_ALLOW" authzActionEnumId="AUTHZA_ALL"/>
83 105
84 <!-- Give ALL users access to security entities needed for permission checks --> 106 <!-- Give ALL users access to security entities needed for permission checks -->
85 <moqui.security.ArtifactAuthz userGroupId="ALL_USERS" artifactGroupId="McpSecurityEntities" authzTypeEnumId="AUTHZT_ALLOW" authzActionEnumId="AUTHZA_ALL"/> 107 <moqui.security.ArtifactAuthz userGroupId="ALL_USERS" artifactGroupId="McpSecurityEntities" authzTypeEnumId="AUTHZT_ALLOW" authzActionEnumId="AUTHZA_ALL"/>
86 108
87 <!-- Ensure ADMIN user always has access to security entities needed for permission checks --> 109 <!-- Ensure ADMIN user always has access to security entities needed for permission checks -->
88 <moqui.security.ArtifactAuthz userGroupId="ADMIN" artifactGroupId="McpServices" authzTypeEnumId="AUTHZT_ALWAYS" authzActionEnumId="AUTHZA_ALL"/> 110 <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"/>
112 <moqui.security.ArtifactAuthz userGroupId="ADMIN" artifactGroupId="McpScreenTools" authzTypeEnumId="AUTHZT_ALWAYS" authzActionEnumId="AUTHZA_ALL"/>
89 113
90 <!-- MCP Business Group Authz --> 114 <!-- MCP Business Group Authz -->
91 <moqui.security.ArtifactAuthz userGroupId="MCP_BUSINESS" artifactGroupId="McpServices" authzTypeEnumId="AUTHZT_ALLOW" authzActionEnumId="AUTHZA_ALL"/> 115 <moqui.security.ArtifactAuthz userGroupId="MCP_BUSINESS" artifactGroupId="McpServices" authzTypeEnumId="AUTHZT_ALLOW" authzActionEnumId="AUTHZA_ALL"/>
92 <moqui.security.ArtifactAuthz userGroupId="MCP_BUSINESS" artifactGroupId="McpBusinessServices" authzTypeEnumId="AUTHZT_ALLOW" authzActionEnumId="AUTHZA_ALL"/> 116 <moqui.security.ArtifactAuthz userGroupId="MCP_BUSINESS" artifactGroupId="McpBusinessServices" authzTypeEnumId="AUTHZT_ALLOW" authzActionEnumId="AUTHZA_ALL"/>
93 <moqui.security.ArtifactAuthz userGroupId="MCP_BUSINESS" artifactGroupId="McpRestPaths" authzTypeEnumId="AUTHZT_ALLOW" authzActionEnumId="AUTHZA_ALL"/> 117 <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"/>
119 <moqui.security.ArtifactAuthz userGroupId="MCP_BUSINESS" artifactGroupId="McpScreenTools" authzTypeEnumId="AUTHZT_ALLOW" authzActionEnumId="AUTHZA_ALL"/>
94 120
95 121
96 <!-- MCP User Accounts --> 122 <!-- MCP User Accounts -->
...@@ -99,6 +125,7 @@ ...@@ -99,6 +125,7 @@
99 125
100 <!-- Add MCP users to MCP user groups --> 126 <!-- Add MCP users to MCP user groups -->
101 <moqui.security.UserGroupMember userGroupId="McpUser" userId="MCP_USER" fromDate="2025-01-01 00:00:00.000"/> 127 <moqui.security.UserGroupMember userGroupId="McpUser" userId="MCP_USER" fromDate="2025-01-01 00:00:00.000"/>
128 <moqui.security.UserGroupMember userGroupId="McpUser" userId="JohnSales" fromDate="2025-01-01 00:00:00.000"/>
102 <moqui.security.UserGroupMember userGroupId="MCP_BUSINESS" userId="MCP_BUSINESS" fromDate="2025-01-01 00:00:00.000"/> 129 <moqui.security.UserGroupMember userGroupId="MCP_BUSINESS" userId="MCP_BUSINESS" fromDate="2025-01-01 00:00:00.000"/>
103 <!-- ADMIN user doesn't need to be in MCP groups - should have full access by default --> 130 <!-- ADMIN user doesn't need to be in MCP groups - should have full access by default -->
104 131
......
...@@ -331,6 +331,22 @@ ...@@ -331,6 +331,22 @@
331 } 331 }
332 } 332 }
333 333
334 // Add screen-based tools
335 try {
336 def screenToolsResult = ec.service.sync().name("McpServices.discover#ScreensAsMcpTools")
337 .parameters([sessionId: sessionId])
338 .requireNewTransaction(false) // Use current transaction
339 .disableAuthz()
340 .call()
341
342 if (screenToolsResult?.tools) {
343 availableTools.addAll(screenToolsResult.tools)
344 ec.logger.info("MCP ToolsList: Added ${screenToolsResult.tools.size()} screen-based tools")
345 }
346 } catch (Exception e) {
347 ec.logger.warn("Error discovering screen-based tools: ${e.message}")
348 }
349
334 // Implement pagination according to MCP spec 350 // Implement pagination according to MCP spec
335 def pageSize = 50 // Reasonable page size for tool lists 351 def pageSize = 50 // Reasonable page size for tool lists
336 def startIndex = 0 352 def startIndex = 0
...@@ -516,7 +532,7 @@ ...@@ -516,7 +532,7 @@
516 // Use curated list of commonly used entities instead of discovering all entities 532 // Use curated list of commonly used entities instead of discovering all entities
517 def availableResources = [] 533 def availableResources = []
518 534
519 ec.logger.info("MCP ResourcesList: Starting permissions-based entity discovery") 535 ec.logger.info("MCP ResourcesList: Starting permissions-based entity discovery ${userGroups}")
520 536
521 // Get user's accessible entities using Moqui's optimized ArtifactAuthzCheckView 537 // Get user's accessible entities using Moqui's optimized ArtifactAuthzCheckView
522 def userAccessibleEntities = null as Set<String> 538 def userAccessibleEntities = null as Set<String>
...@@ -889,6 +905,334 @@ ...@@ -889,6 +905,334 @@
889 </actions> 905 </actions>
890 </service> 906 </service>
891 907
908 <!-- Screen-based MCP Services -->
909
910 <service verb="discover" noun="ScreensAsMcpTools" authenticate="true" allow-remote="true" transaction-timeout="60">
911 <description>Discover screens accessible to user and convert them to MCP tools</description>
912 <in-parameters>
913 <parameter name="sessionId"/>
914 <parameter name="screenPathPattern" required="false"><description>Optional pattern to filter screen paths (supports wildcards)</description></parameter>
915 </in-parameters>
916 <out-parameters>
917 <parameter name="tools" type="List"/>
918 </out-parameters>
919 <actions>
920 <script><![CDATA[
921 import org.moqui.context.ExecutionContext
922 import org.moqui.impl.context.UserFacadeImpl.UserInfo
923 import org.moqui.impl.screen.ScreenDefinition
924
925 ExecutionContext ec = context.ec
926
927 def originalUsername = ec.user.username
928 def originalUserId = ec.user.userId
929 def userGroups = ec.user.getUserGroupIdSet().collect { it }
930
931 ec.logger.info("MCP Screen Discovery: Starting for user ${originalUsername} (${originalUserId}) with groups ${userGroups}")
932
933 def tools = []
934
935 // Get user's accessible screens using ArtifactAuthzCheckView
936 def userAccessibleScreens = null as Set<String>
937 UserInfo adminUserInfo = null
938 try {
939 adminUserInfo = ec.user.pushUser("ADMIN")
940 def aacvList = ec.entity.find("moqui.security.ArtifactAuthzCheckView")
941 .condition("userGroupId", userGroups)
942 .condition("artifactTypeEnumId", "AT_XML_SCREEN")
943 .useCache(true)
944 .disableAuthz()
945 .list()
946 userAccessibleScreens = aacvList.collect { it.artifactName } as Set<String>
947 } finally {
948 if (adminUserInfo != null) {
949 ec.user.popUser()
950 }
951 }
952
953 ec.logger.info("MCP Screen Discovery: Found ${userAccessibleScreens.size()} accessible screens")
954
955 // Helper function to check if user has permission to a screen
956 def userHasScreenPermission = { screenPath ->
957 return userAccessibleScreens != null && userAccessibleScreens.contains(screenPath.toString())
958 }
959
960 // Get all screen definitions and convert accessible ones to MCP tools
961 try {
962 adminUserInfo = ec.user.pushUser("ADMIN")
963
964 // Get screen locations from component configuration and known screen paths
965 def screenPaths = []
966
967 // Common screen paths to check (using existing Moqui screens)
968 def commonScreenPaths = [
969 "apps/ScreenTree",
970 "apps/AppList",
971 "webroot/apps",
972 "webroot/ChangePassword",
973 "webroot/error",
974 "webroot/apps/AppList",
975 "webroot/apps/ScreenTree",
976 "webroot/apps/ScreenTree/ScreenTreeNested"
977 ]
978
979 // Add component-specific screens
980 def componentScreenLocs = ec.entity.find("moqui.screen.SubscreensItem")
981 .selectFields(["screenLocation", "subscreenLocation"])
982 .disableAuthz()
983 .distinct(true)
984 .list()
985
986 for (compScreen in componentScreenLocs) {
987 if (compScreen.subscreenLocation) {
988 screenPaths << compScreen.subscreenLocation
989 }
990 }
991
992 // Combine all screen paths
993 screenPaths.addAll(commonScreenPaths)
994 screenPaths = screenPaths.unique()
995
996 // Filter by pattern if provided
997 if (screenPathPattern) {
998 def pattern = screenPathPattern.replace("*", ".*")
999 screenPaths = screenPaths.findAll { it.matches(pattern) }
1000 }
1001
1002 ec.logger.info("MCP Screen Discovery: Checking ${screenPaths.size()} screen paths")
1003
1004 for (screenPath in screenPaths) {
1005 try {
1006 // Check if user has permission to this screen
1007 if (userHasScreenPermission(screenPath)) {
1008 def tool = convertScreenToMcpTool(screenPath, ec)
1009 if (tool) {
1010 tools << tool
1011 }
1012 }
1013 } catch (Exception e) {
1014 ec.logger.debug("Error processing screen ${screenPath}: ${e.message}")
1015 }
1016 }
1017
1018 } finally {
1019 if (adminUserInfo != null) {
1020 ec.user.popUser()
1021 }
1022 }
1023
1024 ec.logger.info("MCP Screen Discovery: Converted ${tools.size()} screens to MCP tools for user ${originalUsername}")
1025
1026 ]]></script>
1027 </actions>
1028 </service>
1029
1030 <service verb="convert" noun="ScreenToMcpTool" authenticate="false">
1031 <description>Convert a screen path to MCP tool format</description>
1032 <in-parameters>
1033 <parameter name="screenPath" required="true"/>
1034 </in-parameters>
1035 <out-parameters>
1036 <parameter name="tool" type="Map"/>
1037 </out-parameters>
1038 <actions>
1039 <script><![CDATA[
1040 import org.moqui.context.ExecutionContext
1041
1042 ExecutionContext ec = context.ec
1043
1044 tool = null
1045 try {
1046 // Try to get screen definition
1047 def screenDef = null
1048 try {
1049 screenDef = ec.screen.getScreenDefinition(screenPath)
1050 } catch (Exception e) {
1051 // Screen might not exist or be accessible
1052 return
1053 }
1054
1055 if (!screenDef) {
1056 return
1057 }
1058
1059 // Extract screen information
1060 def screenName = screenPath.replaceAll("[^a-zA-Z0-9]", "_")
1061 def title = screenDef.getScreenName() ?: screenPath.split("/")[-1]
1062 def description = screenDef.getDescription() ?: "Moqui screen: ${screenPath}"
1063
1064 // Get screen parameters from transitions and forms
1065 def parameters = [:]
1066 def required = []
1067
1068 try {
1069 // Get transitions for parameter discovery
1070 def transitions = screenDef.getTransitionMap()
1071 transitions.each { transitionName, transition ->
1072 transition.getPathParameterList().each { param ->
1073 parameters[param] = [
1074 type: "string",
1075 description: "Path parameter: ${param}"
1076 ]
1077 required << param
1078 }
1079
1080 // Get single service parameters if transition calls a service
1081 def serviceName = transition.getSingleServiceName()
1082 if (serviceName) {
1083 try {
1084 def serviceDef = ec.service.getServiceDefinition(serviceName)
1085 if (serviceDef) {
1086 def inParamNames = serviceDef.getInParameterNames()
1087 for (paramName in inParamNames) {
1088 def paramNode = serviceDef.getInParameter(paramName)
1089 def paramType = paramNode?.attribute('type') ?: 'String'
1090 def paramDesc = paramNode.first("description")?.text ?: "Parameter from service ${serviceName}"
1091
1092 // Convert Moqui type to JSON Schema type
1093 def typeMap = [
1094 "text-short": "string",
1095 "text-medium": "string",
1096 "text-long": "string",
1097 "text-very-long": "string",
1098 "id": "string",
1099 "id-long": "string",
1100 "number-integer": "integer",
1101 "number-decimal": "number",
1102 "number-float": "number",
1103 "date": "string",
1104 "date-time": "string",
1105 "date-time-nano": "string",
1106 "boolean": "boolean",
1107 "text-indicator": "boolean"
1108 ]
1109 def jsonSchemaType = typeMap[paramType] ?: "string"
1110
1111 parameters[paramName] = [
1112 type: jsonSchemaType,
1113 description: paramDesc
1114 ]
1115
1116 if (paramNode?.attribute('required') == "true") {
1117 required << paramName
1118 }
1119 }
1120 }
1121 } catch (Exception e) {
1122 ec.logger.debug("Error getting service definition for ${serviceName}: ${e.message}")
1123 }
1124 }
1125 }
1126 } catch (Exception e) {
1127 ec.logger.debug("Error getting transitions for screen ${screenPath}: ${e.message}")
1128 }
1129
1130 // Build MCP tool
1131 tool = [
1132 name: "screen_${screenName}",
1133 title: title,
1134 description: "${description}. This tool renders the Moqui screen '${screenPath}' and returns the output.",
1135 inputSchema: [
1136 type: "object",
1137 properties: parameters,
1138 required: required.unique()
1139 ]
1140 ]
1141
1142 // Add screen metadata
1143 tool.screenPath = screenPath
1144 tool.toolType = "screen"
1145
1146 } catch (Exception e) {
1147 ec.logger.warn("Error converting screen ${screenPath} to MCP tool: ${e.message}")
1148 }
1149 ]]></script>
1150 </actions>
1151 </service>
1152
1153 <service verb="execute" noun="ScreenAsMcpTool" authenticate="true" allow-remote="true" transaction-timeout="120">
1154 <description>Execute a screen as an MCP tool</description>
1155 <in-parameters>
1156 <parameter name="screenPath" required="true"/>
1157 <parameter name="parameters" type="Map"><description>Parameters to pass to the screen</description></parameter>
1158 <parameter name="renderMode" default="json"><description>Render mode: json, text, csv, xml</description></parameter>
1159 </in-parameters>
1160 <out-parameters>
1161 <parameter name="result" type="Map"/>
1162 </out-parameters>
1163 <actions>
1164 <script><![CDATA[
1165 import org.moqui.context.ExecutionContext
1166 import groovy.json.JsonBuilder
1167
1168 ExecutionContext ec = context.ec
1169
1170 def startTime = System.currentTimeMillis()
1171 try {
1172 // Validate screen exists
1173 if (!ec.screen.isScreenDefined(screenPath)) {
1174 throw new Exception("Screen not found: ${screenPath}")
1175 }
1176
1177 // Set parameters in context
1178 if (parameters) {
1179 ec.context.putAll(parameters)
1180 }
1181
1182 // Render screen
1183 def screenRender = ec.screen.makeRender()
1184 .screenPath(screenPath)
1185 .renderMode(renderMode)
1186
1187 def output = screenRender.render()
1188 def executionTime = (System.currentTimeMillis() - startTime) / 1000.0
1189
1190 // Convert to MCP format
1191 def content = []
1192 if (output && output.trim().length() > 0) {
1193 content << [
1194 type: "text",
1195 text: output
1196 ]
1197 }
1198
1199 result = [
1200 content: content,
1201 isError: false,
1202 metadata: [
1203 screenPath: screenPath,
1204 renderMode: renderMode,
1205 executionTime: executionTime,
1206 outputLength: output?.length() ?: 0
1207 ]
1208 ]
1209
1210 ec.logger.info("MCP Screen Execution: Successfully executed screen ${screenPath} in ${executionTime}s")
1211
1212 } catch (Exception e) {
1213 def executionTime = (System.currentTimeMillis() - startTime) / 1000.0
1214
1215 result = [
1216 content: [
1217 [
1218 type: "text",
1219 text: "Error executing screen ${screenPath}: ${e.message}"
1220 ]
1221 ],
1222 isError: true,
1223 metadata: [
1224 screenPath: screenPath,
1225 renderMode: renderMode,
1226 executionTime: executionTime
1227 ]
1228 ]
1229
1230 ec.logger.error("MCP Screen Execution error for ${screenPath}", e)
1231 }
1232 ]]></script>
1233 </actions>
1234 </service>
1235
892 <!-- NOTE: handle#McpRequest service removed - functionality moved to screen/webapp.xml for unified handling --> 1236 <!-- NOTE: handle#McpRequest service removed - functionality moved to screen/webapp.xml for unified handling -->
893 1237
894 </services> 1238 </services>
...\ No newline at end of file ...\ No newline at end of file
......
...@@ -208,6 +208,7 @@ try { ...@@ -208,6 +208,7 @@ try {
208 // Look up the actual Visit EntityValue 208 // Look up the actual Visit EntityValue
209 visit = ec.entity.find("moqui.server.Visit") 209 visit = ec.entity.find("moqui.server.Visit")
210 .condition("visitId", visitResult.visitId) 210 .condition("visitId", visitResult.visitId)
211 .disableAuthz()
211 .one() 212 .one()
212 if (!visit) { 213 if (!visit) {
213 throw new Exception("Failed to look up newly created Visit") 214 throw new Exception("Failed to look up newly created Visit")
...@@ -339,6 +340,7 @@ logger.info("Handling Enhanced SSE connection from ${request.remoteAddr}") ...@@ -339,6 +340,7 @@ logger.info("Handling Enhanced SSE connection from ${request.remoteAddr}")
339 // Look up the actual Visit EntityValue 340 // Look up the actual Visit EntityValue
340 visit = ec.entity.find("moqui.server.Visit") 341 visit = ec.entity.find("moqui.server.Visit")
341 .condition("visitId", visitResult.visitId) 342 .condition("visitId", visitResult.visitId)
343 .disableAuthz()
342 .one() 344 .one()
343 if (!visit) { 345 if (!visit) {
344 throw new Exception("Failed to look up newly created Visit") 346 throw new Exception("Failed to look up newly created Visit")
...@@ -468,6 +470,7 @@ logger.info("Handling Enhanced SSE connection from ${request.remoteAddr}") ...@@ -468,6 +470,7 @@ logger.info("Handling Enhanced SSE connection from ${request.remoteAddr}")
468 // Get Visit directly - this is our session 470 // Get Visit directly - this is our session
469 def visit = ec.entity.find("moqui.server.Visit") 471 def visit = ec.entity.find("moqui.server.Visit")
470 .condition("visitId", sessionId) 472 .condition("visitId", sessionId)
473 .disableAuthz()
471 .one() 474 .one()
472 475
473 if (!visit) { 476 if (!visit) {
...@@ -724,6 +727,7 @@ logger.info("Handling Enhanced SSE connection from ${request.remoteAddr}") ...@@ -724,6 +727,7 @@ logger.info("Handling Enhanced SSE connection from ${request.remoteAddr}")
724 try { 727 try {
725 def existingVisit = ec.entity.find("moqui.server.Visit") 728 def existingVisit = ec.entity.find("moqui.server.Visit")
726 .condition("visitId", sessionId) 729 .condition("visitId", sessionId)
730 .disableAuthz()
727 .one() 731 .one()
728 732
729 if (!existingVisit) { 733 if (!existingVisit) {
...@@ -925,6 +929,7 @@ logger.info("Handling Enhanced SSE connection from ${request.remoteAddr}") ...@@ -925,6 +929,7 @@ logger.info("Handling Enhanced SSE connection from ${request.remoteAddr}")
925 // Look up all MCP Visits (persistent) 929 // Look up all MCP Visits (persistent)
926 def mcpVisits = ec.entity.find("moqui.server.Visit") 930 def mcpVisits = ec.entity.find("moqui.server.Visit")
927 .condition("initialRequest", "like", "%mcpSession%") 931 .condition("initialRequest", "like", "%mcpSession%")
932 .disableAuthz()
928 .list() 933 .list()
929 934
930 logger.info("Broadcasting to ${mcpVisits.size()} MCP visits, ${activeConnections.size()} active connections") 935 logger.info("Broadcasting to ${mcpVisits.size()} MCP visits, ${activeConnections.size()} active connections")
...@@ -985,6 +990,7 @@ logger.info("Handling Enhanced SSE connection from ${request.remoteAddr}") ...@@ -985,6 +990,7 @@ logger.info("Handling Enhanced SSE connection from ${request.remoteAddr}")
985 // Look up all MCP Visits (persistent) 990 // Look up all MCP Visits (persistent)
986 def mcpVisits = ec.entity.find("moqui.server.Visit") 991 def mcpVisits = ec.entity.find("moqui.server.Visit")
987 .condition("initialRequest", "like", "%mcpSession%") 992 .condition("initialRequest", "like", "%mcpSession%")
993 .disableAuthz()
988 .list() 994 .list()
989 995
990 return [ 996 return [
......