df9e7244 by Ean Schuessler

Continuing to flesh out MCP connectivity

1 parent 7abaf27f
...@@ -30,6 +30,21 @@ ...@@ -30,6 +30,21 @@
30 <set field="locale" from="ec.user?.locale ?: 'en_US'"/> 30 <set field="locale" from="ec.user?.locale ?: 'en_US'"/>
31 </actions> 31 </actions>
32 32
33 <transition name="fixConfig">
34 <actions>
35 <script><![CDATA[
36 ec.entity.find("moqui.mcp.agent.ProductStoreAiConfig")
37 .condition("productStoreId", "POPC_DEFAULT")
38 .condition("aiConfigId", "DEFAULT")
39 .one()
40 .set("modelName", "devstral")
41 .update()
42 ]]></script>
43 <set field="message" value="Config updated successfully to devstral"/>
44 </actions>
45 <default-response type="screen-last"/>
46 </transition>
47
33 <widgets> 48 <widgets>
34 <container style="mcp-test-screen"> 49 <container style="mcp-test-screen">
35 <container style="text-center"> 50 <container style="text-center">
......
...@@ -193,7 +193,9 @@ ...@@ -193,7 +193,9 @@
193 def internalToolMappings = [ 193 def internalToolMappings = [
194 "moqui_search_screens": "McpServices.mcp#SearchScreens", 194 "moqui_search_screens": "McpServices.mcp#SearchScreens",
195 "moqui_get_screen_details": "McpServices.mcp#GetScreenDetails", 195 "moqui_get_screen_details": "McpServices.mcp#GetScreenDetails",
196 "moqui_get_help": "McpServices.mcp#GetHelp" 196 "moqui_get_help": "McpServices.mcp#GetHelp",
197 "moqui_prompts_list": "McpServices.mcp#PromptsList",
198 "moqui_prompts_get": "McpServices.mcp#PromptsGet"
197 // "moqui_batch_operations": "McpServices.mcp#BatchOperations" - hidden until fixed 199 // "moqui_batch_operations": "McpServices.mcp#BatchOperations" - hidden until fixed
198 ] 200 ]
199 201
...@@ -655,15 +657,15 @@ def getWikiInstructions = { lookupPath -> ...@@ -655,15 +657,15 @@ def getWikiInstructions = { lookupPath ->
655 if (!wikiSpace) continue 657 if (!wikiSpace) continue
656 658
657 // Build the resource location for the page 659 // Build the resource location for the page
660 // rootPageLocation is dbresource://WikiSpace/MCP_PROMPTS.md
661 // Need to construct: dbresource://WikiSpace/MCP_PROMPTS/get-started.md
662 // TEST - adding marker
658 def pageLocation = wikiSpace.rootPageLocation 663 def pageLocation = wikiSpace.rootPageLocation
659 if (!pageLocation.endsWith('/')) { 664 // Replace .md with /pagePath.md
660 pageLocation += '/' 665 if (pageLocation.endsWith('.md')) {
666 pageLocation = pageLocation.substring(0, pageLocation.length() - 3) + '/' + wikiPage.pagePath + '.md'
661 } 667 }
662 pageLocation += wikiPage.pagePath + '.md' 668 ec.logger.error("MCP PromptsGet: TEST MARKER - Using location: ${pageLocation}")
663
664 // Get the resource reference and text content
665 def pageRef = ec.resource.getLocationReference(pageLocation)
666 def wikiText = pageRef?.getText()
667 669
668 if (wikiText) { 670 if (wikiText) {
669 if (tryPath != normalizedPath) { 671 if (tryPath != normalizedPath) {
...@@ -2107,20 +2109,25 @@ def wikiInstructions = getWikiInstructions(inputScreenPath) ...@@ -2107,20 +2109,25 @@ def wikiInstructions = getWikiInstructions(inputScreenPath)
2107 .list() 2109 .list()
2108 2110
2109 for (def wp in wikiPageList) { 2111 for (def wp in wikiPageList) {
2110 // Try to load argument schema from attachment 2112 // Try to load argument schema from DbResource
2111 def arguments = [] 2113 def arguments = []
2112 try { 2114 try {
2113 def attachment = ec.entity.find("moqui.resource.wiki.WikiPageAttachment") 2115 // Build resourceId for arguments file (e.g., WIKI_MCP_GET_STARTED_ARGS)
2114 .condition("wikiPageId", wp.wikiPageId) 2116 def argsResourceId = "WIKI_MCP_${wp.pagePath.toUpperCase().replace('-', '_')}_ARGS"
2115 .condition("filename", "arguments.json") 2117 def dbResource = ec.entity.find("moqui.resource.DbResource")
2118 .condition("resourceId", argsResourceId)
2116 .one() 2119 .one()
2117 if (attachment) { 2120 if (dbResource) {
2118 def attachmentRef = ec.resource.getLocationReference(attachment.getLocation()) 2121 def dbResourceFile = ec.entity.find("moqui.resource.DbResourceFile")
2119 def jsonText = attachmentRef?.getText() 2122 .condition("resourceId", argsResourceId)
2123 .one()
2124 if (dbResourceFile) {
2125 def jsonText = dbResourceFile.fileData?.getText()
2120 if (jsonText) { 2126 if (jsonText) {
2121 arguments = new JsonSlurper().parseText(jsonText) ?: [] 2127 arguments = new JsonSlurper().parseText(jsonText) ?: []
2122 } 2128 }
2123 } 2129 }
2130 }
2124 } catch (Exception e) { 2131 } catch (Exception e) {
2125 ec.logger.debug("Could not parse arguments for ${wp.pagePath}: ${e.message}") 2132 ec.logger.debug("Could not parse arguments for ${wp.pagePath}: ${e.message}")
2126 } 2133 }
...@@ -2156,13 +2163,22 @@ def wikiInstructions = getWikiInstructions(inputScreenPath) ...@@ -2156,13 +2163,22 @@ def wikiInstructions = getWikiInstructions(inputScreenPath)
2156 2163
2157 ExecutionContext ec = context.ec 2164 ExecutionContext ec = context.ec
2158 2165
2159 ec.logger.info("MCP PromptsGet: Retrieving prompt '${name}' from wiki space MCP_PROMPTS") 2166 ec.logger.info("MCP PromptsGet: START v2.0 - Retrieving prompt '${name}' from wiki space MCP_PROMPTS")
2167
2168 // Debug: Check what wiki pages exist in MCP_PROMPTS space
2169 def allPages = ec.entity.find("moqui.resource.wiki.WikiPage")
2170 .condition("wikiSpaceId", "MCP_PROMPTS")
2171 .useCache(true)
2172 .list()
2173 ec.logger.info("MCP PromptsGet: All pages in MCP_PROMPTS space: ${allPages.collect { [pageId: it.wikiPageId, pagePath: it.pagePath] }}")
2160 2174
2161 // Get the wiki page for this prompt 2175 // Get the wiki page for this prompt
2162 def wikiPage = ec.entity.find("moqui.resource.wiki.WikiPage") 2176 def wikiPage = ec.entity.find("moqui.resource.wiki.WikiPage")
2163 .condition("wikiSpaceId", "MCP_PROMPTS") 2177 .condition("wikiSpaceId", "MCP_PROMPTS")
2164 .condition("pagePath", name) 2178 .condition("pagePath", name)
2179 .useCache(true)
2165 .one() 2180 .one()
2181 ec.logger.info("MCP PromptsGet: Looking for pagePath='${name}', found: ${wikiPage?.wikiPageId}")
2166 2182
2167 if (!wikiPage) { 2183 if (!wikiPage) {
2168 throw new Exception("Prompt not found: ${name}") 2184 throw new Exception("Prompt not found: ${name}")
...@@ -2171,27 +2187,57 @@ def wikiInstructions = getWikiInstructions(inputScreenPath) ...@@ -2171,27 +2187,57 @@ def wikiInstructions = getWikiInstructions(inputScreenPath)
2171 // Get the wiki space to build the page location 2187 // Get the wiki space to build the page location
2172 def wikiSpace = ec.entity.find("moqui.resource.wiki.WikiSpace") 2188 def wikiSpace = ec.entity.find("moqui.resource.wiki.WikiSpace")
2173 .condition("wikiSpaceId", "MCP_PROMPTS") 2189 .condition("wikiSpaceId", "MCP_PROMPTS")
2190 .useCache(true)
2174 .one() 2191 .one()
2175 2192
2176 if (!wikiSpace) { 2193 if (!wikiSpace) {
2177 throw new Exception("MCP Prompts wiki space not found") 2194 throw new Exception("MCP Prompts wiki space not found")
2178 } 2195 }
2179 2196
2180 // Build the resource location for the page (root + page path + .md) 2197 // Build resource location using framework's findChildFile pattern
2181 def pageLocation = wikiSpace.rootPageLocation 2198 // Note: pagePath is "get-started" but file is "get-started.md"
2182 if (!pageLocation.endsWith('/')) { 2199 ec.logger.info("MCP PromptsGet: rootPageLocation=${wikiSpace.rootPageLocation}, pagePath=${wikiPage.pagePath}")
2183 pageLocation += '/' 2200 def rootPageRef = ec.resource.getLocationReference(wikiSpace.rootPageLocation)
2201 ec.logger.info("MCP PromptsGet: rootPageRef.location=${rootPageRef?.location}")
2202
2203 // Try with .md extension first, then without
2204 def pageRef = rootPageRef.findChildFile(wikiPage.pagePath + '.md')
2205 if (!pageRef) {
2206 pageRef = rootPageRef.findChildFile(wikiPage.pagePath)
2184 } 2207 }
2185 pageLocation += name + '.md' 2208 ec.logger.info("MCP PromptsGet: pageRef.location=${pageRef?.location}")
2186 2209
2187 // Get the resource reference and text content
2188 def pageRef = ec.resource.getLocationReference(pageLocation)
2189 def templateText = pageRef?.getText() 2210 def templateText = pageRef?.getText()
2211 ec.logger.info("MCP PromptsGet: templateText.length=${templateText?.length() ?: 'null'}")
2190 2212
2191 if (!templateText) { 2213 if (!templateText) {
2192 throw new Exception("Prompt template not found: ${name}") 2214 throw new Exception("Prompt template not found: ${name}")
2193 } 2215 }
2194 2216
2217 // Load arguments schema from DbResource for prompt metadata
2218 def promptArguments = []
2219 try {
2220 def argsResourceId = "WIKI_MCP_${name.toUpperCase().replace('-', '_')}_ARGS"
2221 def dbResource = ec.entity.find("moqui.resource.DbResource")
2222 .condition("resourceId", argsResourceId)
2223 .useCache(true)
2224 .one()
2225 if (dbResource) {
2226 def dbResourceFile = ec.entity.find("moqui.resource.DbResourceFile")
2227 .condition("resourceId", argsResourceId)
2228 .useCache(true)
2229 .one()
2230 if (dbResourceFile) {
2231 def jsonText = dbResourceFile.fileData?.getText()
2232 if (jsonText) {
2233 promptArguments = new JsonSlurper().parseText(jsonText) ?: []
2234 }
2235 }
2236 }
2237 } catch (Exception e) {
2238 ec.logger.debug("Could not parse arguments for ${name}: ${e.message}")
2239 }
2240
2195 // Render template using Groovy GString engine 2241 // Render template using Groovy GString engine
2196 def templateEngine = new GStringTemplateEngine() 2242 def templateEngine = new GStringTemplateEngine()
2197 def template = templateEngine.createTemplate(templateText) 2243 def template = templateEngine.createTemplate(templateText)
...@@ -2202,6 +2248,7 @@ def wikiInstructions = getWikiInstructions(inputScreenPath) ...@@ -2202,6 +2248,7 @@ def wikiInstructions = getWikiInstructions(inputScreenPath)
2202 2248
2203 result = [ 2249 result = [
2204 description: "MCP prompt template", 2250 description: "MCP prompt template",
2251 arguments: promptArguments,
2205 messages: [[ 2252 messages: [[
2206 role: "user", 2253 role: "user",
2207 content: [type: "text", text: rendered] 2254 content: [type: "text", text: rendered]
...@@ -3011,7 +3058,7 @@ def wikiInstructions = getWikiInstructions(inputScreenPath) ...@@ -3011,7 +3058,7 @@ def wikiInstructions = getWikiInstructions(inputScreenPath)
3011 // moqui_batch_operations - hidden until fixed 3058 // moqui_batch_operations - hidden until fixed
3012 // 3059 //
3013 [ 3060 [
3014 name: "prompts_list", 3061 name: "moqui_prompts_list",
3015 title: "List Prompts", 3062 title: "List Prompts",
3016 description: "List available MCP prompt templates.", 3063 description: "List available MCP prompt templates.",
3017 inputSchema: [ 3064 inputSchema: [
...@@ -3020,7 +3067,7 @@ def wikiInstructions = getWikiInstructions(inputScreenPath) ...@@ -3020,7 +3067,7 @@ def wikiInstructions = getWikiInstructions(inputScreenPath)
3020 ] 3067 ]
3021 ], 3068 ],
3022 [ 3069 [
3023 name: "prompts_get", 3070 name: "moqui_prompts_get",
3024 title: "Get Prompt", 3071 title: "Get Prompt",
3025 description: "Retrieve and render a specific MCP prompt template.", 3072 description: "Retrieve and render a specific MCP prompt template.",
3026 inputSchema: [ 3073 inputSchema: [
......
1 <?xml version="1.0" encoding="UTF-8"?>
2 <services xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3 xsi:noNamespaceSchemaLocation="http://moqui.org/xsd/service-definition-3.xsd">
4
5 <service verb="update" noun="ModelName" authenticate="false">
6 <description>Update modelName in ProductStoreAiConfig</description>
7 <actions>
8 <script><![CDATA[
9 def config = ec.entity.find("moqui.mcp.agent.ProductStoreAiConfig")
10 .condition("productStoreId", "POPC_DEFAULT")
11 .condition("aiConfigId", "DEFAULT")
12 .one()
13
14 if (config) {
15 ec.logger.info("UPDATE MODEL NAME: Current=${config.modelName}")
16 config.modelName = "devstral"
17 config.update()
18 ec.logger.info("UPDATE MODEL NAME: Updated to=${config.modelName}")
19 return "Updated modelName to devstral"
20 } else {
21 ec.logger.warn("UPDATE MODEL NAME: Config not found")
22 return "Config not found"
23 }
24 ]]></script>
25 </actions>
26 </service>
27 </services>