Refactor wiki system - remove McpScreenDoc entity
- Remove McpScreenDoc entity and mapping layer - Use screen paths directly as WikiPage.pagePath - Fix historySeqId from string "01" to numeric "1" - Fix DbResourceFile fileData to use CDATA for complex content - Add wiki descriptions to BrowseScreens subscreens - Update BrowseScreens to query WikiPage directly by screenPath - Remove duplicate/corrupt data entries from McpScreenDocsData.xml
Showing
3 changed files
with
439 additions
and
8 deletions
| ... | @@ -52,7 +52,7 @@ | ... | @@ -52,7 +52,7 @@ |
| 52 | <!-- WikiPageHistory for version tracking --> | 52 | <!-- WikiPageHistory for version tracking --> |
| 53 | <moqui.resource.wiki.WikiPageHistory | 53 | <moqui.resource.wiki.WikiPageHistory |
| 54 | wikiPageId="MCP_PROMPTS/get-started" | 54 | wikiPageId="MCP_PROMPTS/get-started" |
| 55 | historySeqId="01" | 55 | historySeqId="1" |
| 56 | versionName="v1" | 56 | versionName="v1" |
| 57 | userId="EX_JOHN_DOE" | 57 | userId="EX_JOHN_DOE" |
| 58 | changeDateTime="2025-12-29 00:00:00.000"/> | 58 | changeDateTime="2025-12-29 00:00:00.000"/> | ... | ... |
data/McpScreenDocsData.xml
0 → 100644
| 1 | <?xml version="1.0" encoding="UTF-8"?> | ||
| 2 | <!-- | ||
| 3 | This software is in the public domain under CC0 1.0 Universal plus a | ||
| 4 | Grant of Patent License. | ||
| 5 | |||
| 6 | To the extent possible under law, the author(s) have dedicated all | ||
| 7 | copyright and related and neighboring rights to this software to the | ||
| 8 | public domain worldwide. This software is distributed without any warranty. | ||
| 9 | |||
| 10 | You should have received a copy of the CC0 Public Domain Dedication | ||
| 11 | along with this software. If not, see | ||
| 12 | <http://creativecommons.org/publicdomain/zero/1.0/>. | ||
| 13 | --> | ||
| 14 | <entity-facade-xml xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
| 15 | xsi:noNamespaceSchemaLocation="http://moqui.org/xsd/entity-facade-3.xsd"> | ||
| 16 | |||
| 17 | <!-- MCP Screen Documentation Wiki Space --> | ||
| 18 | <moqui.resource.wiki.WikiSpace wikiSpaceId="MCP_SCREEN_DOCS" | ||
| 19 | description="MCP Screen Documentation - LLM instructions for specific screens" | ||
| 20 | restrictView="N" | ||
| 21 | restrictUpdate="Y" | ||
| 22 | rootPageLocation="dbresource://WikiSpace/MCP_SCREEN_DOCS.md"/> | ||
| 23 | |||
| 24 | <!-- WikiSpace Root Page --> | ||
| 25 | <moqui.resource.DbResource | ||
| 26 | resourceId="WIKI_MCP_SCREEN_DOCS" | ||
| 27 | parentResourceId="" | ||
| 28 | filename="MCP_SCREEN_DOCS.md" | ||
| 29 | isFile="Y"/> | ||
| 30 | <moqui.resource.DbResourceFile | ||
| 31 | resourceId="WIKI_MCP_SCREEN_DOCS" | ||
| 32 | mimeType="text/markdown" | ||
| 33 | versionName="v1"><![CDATA[# Moqui MCP Server | ||
| 34 | |||
| 35 | This server provides access to Moqui ERP through MCP. | ||
| 36 | |||
| 37 | ## Getting Started | ||
| 38 | |||
| 39 | Use the following discovery tools to explore available functionality: | ||
| 40 | - `moqui_browse_screens`: Browse Moqui screen hierarchy | ||
| 41 | - `moqui_search_screens`: Search for screens by name to find their paths | ||
| 42 | - `moqui_get_screen_details`: Get input parameters for specific screens | ||
| 43 | |||
| 44 | ## Common Screen Paths | ||
| 45 | |||
| 46 | ### Catalog Operations | ||
| 47 | - `PopCommerce.PopCommerceAdmin.Catalog.Product.FindProduct`: Search and browse products | ||
| 48 | - `PopCommerce.PopCommerceAdmin.Catalog.Feature.FindFeature`: Search by features like color or size | ||
| 49 | - `PopCommerce.PopCommerceAdmin.Catalog.Product.EditPrices`: View and update product prices | ||
| 50 | |||
| 51 | ### Order Management | ||
| 52 | - `PopCommerce.PopCommerceAdmin.Order.FindOrder`: Lookup order status and details | ||
| 53 | - `PopCommerce.PopCommerceAdmin.QuickSearch`: General order and customer search | ||
| 54 | |||
| 55 | ### Customer Management | ||
| 56 | - `PopCommerce.PopCommerceRoot.Customer`: Manage customer accounts | ||
| 57 | - `PopCommerce.PopCommerceAdmin.QuickSearch`: Customer lookup | ||
| 58 | |||
| 59 | ## Tips for LLM Clients | ||
| 60 | |||
| 61 | - All screens support parameterized queries for filtering results | ||
| 62 | - Use `moqui_render_screen` with the screen path to execute screens | ||
| 63 | - Screen paths use dot notation (e.g., `PopCommerce.Catalog.Product`) | ||
| 64 | - Check `moqui_get_screen_details` for required parameters before rendering | ||
| 65 | - Use `renderMode: "mcp"` for structured JSON output or `"text"` for human-readable format]]></moqui.resource.DbResourceFile> | ||
| 66 | |||
| 67 | <!-- Root Wiki Page --> | ||
| 68 | <moqui.resource.wiki.WikiPage | ||
| 69 | wikiPageId="MCP_SCREEN_DOCS/root" | ||
| 70 | wikiSpaceId="MCP_SCREEN_DOCS" | ||
| 71 | pagePath="root" | ||
| 72 | publishedVersionName="v1" | ||
| 73 | restrictView="N"> | ||
| 74 | </moqui.resource.wiki.WikiPage> | ||
| 75 | |||
| 76 | <moqui.resource.wiki.WikiPageHistory | ||
| 77 | wikiPageId="MCP_SCREEN_DOCS/root" | ||
| 78 | historySeqId="1" | ||
| 79 | versionName="v1" | ||
| 80 | userId="EX_JOHN_DOE" | ||
| 81 | changeDateTime="2025-01-02 00:00:00.000"/> | ||
| 82 | |||
| 83 | <!-- Root Screen Documentation --> | ||
| 84 | <moqui.resource.DbResource | ||
| 85 | resourceId="WIKI_MCP_DOCS_ROOT" | ||
| 86 | parentResourceId="WIKI_MCP_SCREEN_DOCS" | ||
| 87 | filename="root.md" | ||
| 88 | isFile="Y"/> | ||
| 89 | <moqui.resource.DbResourceFile | ||
| 90 | resourceId="WIKI_MCP_DOCS_ROOT" | ||
| 91 | mimeType="text/markdown" | ||
| 92 | versionName="v1"><![CDATA[# Moqui MCP Server | ||
| 93 | |||
| 94 | This server provides access to Moqui ERP through MCP. | ||
| 95 | |||
| 96 | ## Getting Started | ||
| 97 | |||
| 98 | Use the following discovery tools to explore available functionality: | ||
| 99 | - `moqui_browse_screens`: Browse Moqui screen hierarchy | ||
| 100 | - `moqui_search_screens`: Search for screens by name to find their paths | ||
| 101 | - `moqui_get_screen_details`: Get input parameters for specific screens | ||
| 102 | |||
| 103 | ## Common Screen Paths | ||
| 104 | |||
| 105 | ### Catalog Operations | ||
| 106 | - `PopCommerce.PopCommerceAdmin.Catalog.Product.FindProduct`: Search and browse products | ||
| 107 | - `PopCommerce.PopCommerceAdmin.Catalog.Feature.FindFeature`: Search by features like color or size | ||
| 108 | - `PopCommerce.PopCommerceAdmin.Catalog.Product.EditPrices`: View and update product prices | ||
| 109 | |||
| 110 | ### Order Management | ||
| 111 | - `PopCommerce.PopCommerceAdmin.Order.FindOrder`: Lookup order status and details | ||
| 112 | - `PopCommerce.PopCommerceAdmin.QuickSearch`: General order and customer search | ||
| 113 | |||
| 114 | ### Customer Management | ||
| 115 | - `PopCommerce.PopCommerceRoot.Customer`: Manage customer accounts | ||
| 116 | - `PopCommerce.PopCommerceAdmin.QuickSearch`: Customer lookup | ||
| 117 | |||
| 118 | ## Tips for LLM Clients | ||
| 119 | |||
| 120 | - All screens support parameterized queries for filtering results | ||
| 121 | - Use `moqui_render_screen` with the screen path to execute screens | ||
| 122 | - Screen paths use dot notation (e.g., `PopCommerce.Catalog.Product`) | ||
| 123 | - Check `moqui_get_screen_details` for required parameters before rendering | ||
| 124 | - Use `renderMode: "mcp"` for structured JSON output or `"text"` for human-readable format]]></moqui.resource.DbResourceFile> | ||
| 125 | |||
| 126 | <!-- PopCommerce Root Screen Documentation --> | ||
| 127 | <moqui.resource.DbResource | ||
| 128 | resourceId="WIKI_MCP_DOCS_POPCOMM_ROOT" | ||
| 129 | parentResourceId="WIKI_MCP_SCREEN_DOCS" | ||
| 130 | filename="PopCommerce.PopCommerceRoot.md" | ||
| 131 | isFile="Y"/> | ||
| 132 | <moqui.resource.DbResourceFile | ||
| 133 | resourceId="WIKI_MCP_DOCS_POPCOMM_ROOT" | ||
| 134 | mimeType="text/markdown" | ||
| 135 | versionName="v1"><![CDATA[# PopCommerce Root | ||
| 136 | |||
| 137 | Main storefront and customer-facing screens for PopCommerce e-commerce component. | ||
| 138 | |||
| 139 | ## Key Screens | ||
| 140 | |||
| 141 | - **Customer Management**: Browse and manage customer accounts | ||
| 142 | - **Order Status**: View order history and track shipments | ||
| 143 | - **Product Catalog**: Browse products and categories | ||
| 144 | - **Shopping Cart**: Review and checkout items | ||
| 145 | |||
| 146 | ## Navigation | ||
| 147 | |||
| 148 | Use browse tools to explore the full catalog of PopCommerce screens starting from this root screen.]]></moqui.resource.DbResourceFile> | ||
| 149 | |||
| 150 | <!-- PopCommerce Root Wiki Page --> | ||
| 151 | <moqui.resource.wiki.WikiPage | ||
| 152 | wikiPageId="MCP_SCREEN_DOCS/PopCommerceRoot" | ||
| 153 | wikiSpaceId="MCP_SCREEN_DOCS" | ||
| 154 | pagePath="PopCommerce.PopCommerceRoot" | ||
| 155 | publishedVersionName="v1" | ||
| 156 | restrictView="N"> | ||
| 157 | </moqui.resource.wiki.WikiPage> | ||
| 158 | |||
| 159 | <moqui.resource.wiki.WikiPageHistory | ||
| 160 | wikiPageId="MCP_SCREEN_DOCS/PopCommerceRoot" | ||
| 161 | historySeqId="1" | ||
| 162 | versionName="v1" | ||
| 163 | userId="EX_JOHN_DOE" | ||
| 164 | changeDateTime="2025-01-02 00:00:00.000"/> | ||
| 165 | |||
| 166 | <!-- SimpleScreens Root Documentation --> | ||
| 167 | <moqui.resource.DbResource | ||
| 168 | resourceId="WIKI_MCP_DOCS_SIMPLE_ROOT" | ||
| 169 | parentResourceId="WIKI_MCP_SCREEN_DOCS" | ||
| 170 | filename="SimpleScreens.Root.md" | ||
| 171 | isFile="Y"/> | ||
| 172 | <moqui.resource.DbResourceFile | ||
| 173 | resourceId="WIKI_MCP_DOCS_SIMPLE_ROOT" | ||
| 174 | mimeType="text/markdown" | ||
| 175 | versionName="v1"><![CDATA[# Simple Screens Root | ||
| 176 | |||
| 177 | Basic Moqui framework demonstration screens showing common patterns and examples. | ||
| 178 | |||
| 179 | ## Screens | ||
| 180 | |||
| 181 | - **Hello World**: Simple text rendering example | ||
| 182 | - **Examples**: Various framework demonstration screens | ||
| 183 | - **Forms**: Form input and validation examples | ||
| 184 | - **Lists**: Data list and table examples | ||
| 185 | |||
| 186 | ## Usage | ||
| 187 | |||
| 188 | These screens are primarily for learning Moqui screen development patterns.]]></moqui.resource.DbResourceFile> | ||
| 189 | |||
| 190 | <!-- SimpleScreens Root Wiki Page --> | ||
| 191 | <moqui.resource.wiki.WikiPage | ||
| 192 | wikiPageId="MCP_SCREEN_DOCS/SimpleRoot" | ||
| 193 | wikiSpaceId="MCP_SCREEN_DOCS" | ||
| 194 | pagePath="SimpleScreens.Root" | ||
| 195 | publishedVersionName="v1" | ||
| 196 | restrictView="N"> | ||
| 197 | </moqui.resource.wiki.WikiPage> | ||
| 198 | |||
| 199 | <moqui.resource.wiki.WikiPageHistory | ||
| 200 | wikiPageId="MCP_SCREEN_DOCS/SimpleRoot" | ||
| 201 | historySeqId="1" | ||
| 202 | versionName="v1" | ||
| 203 | userId="EX_JOHN_DOE" | ||
| 204 | changeDateTime="2025-01-02 00:00:00.000"/> | ||
| 205 | |||
| 206 | </entity-facade-xml> |
| ... | @@ -88,6 +88,42 @@ | ... | @@ -88,6 +88,42 @@ |
| 88 | def userId = ec.user.userId | 88 | def userId = ec.user.userId |
| 89 | def userAccountId = userId ? userId : null | 89 | def userAccountId = userId ? userId : null |
| 90 | 90 | ||
| 91 | // Try to load root instructions from wiki | ||
| 92 | def instructions = null | ||
| 93 | try { | ||
| 94 | def wikiPage = ec.entity.find("moqui.resource.wiki.WikiPage") | ||
| 95 | .condition("wikiSpaceId", "MCP_SCREEN_DOCS") | ||
| 96 | .condition("pagePath", "root") | ||
| 97 | .useCache(true) | ||
| 98 | .one() | ||
| 99 | |||
| 100 | if (wikiPage) { | ||
| 101 | def wikiSpace = ec.entity.find("moqui.resource.wiki.WikiSpace") | ||
| 102 | .condition("wikiSpaceId", wikiPage.wikiSpaceId) | ||
| 103 | .one() | ||
| 104 | |||
| 105 | if (wikiSpace) { | ||
| 106 | def pageLocation = wikiSpace.rootPageLocation | ||
| 107 | if (!pageLocation.endsWith('/')) pageLocation += '/' | ||
| 108 | pageLocation += wikiPage.pagePath + '.md' | ||
| 109 | |||
| 110 | def pageRef = ec.resource.getLocationReference(pageLocation) | ||
| 111 | def wikiText = pageRef?.getText() | ||
| 112 | if (wikiText) { | ||
| 113 | instructions = wikiText | ||
| 114 | ec.logger.info("MCP Initialize: Loaded root instructions from wiki") | ||
| 115 | } | ||
| 116 | } | ||
| 117 | } | ||
| 118 | } catch (Exception e) { | ||
| 119 | ec.logger.debug("Could not load root instructions from wiki: ${e.message}") | ||
| 120 | } | ||
| 121 | |||
| 122 | // Fallback to hardcoded instructions if wiki not available | ||
| 123 | if (!instructions) { | ||
| 124 | instructions = "This server provides access to Moqui ERP through MCP. For common business queries: Use PopCommerce.PopCommerceAdmin.Catalog.Feature.FindFeature to search by features like color or size. Use PopCommerce.PopCommerceAdmin.Catalog.Product.FindProduct for product catalog, PopCommerce.PopCommerceAdmin.Order.FindOrder for order status, PopCommerce.PopCommerceRoot.Customer for customer management, PopCommerce.PopCommerceAdmin.Catalog.Product.EditPrices to check prices and PopCommerce.PopCommerceAdmin.QuickSearch for general searches. All screens support parameterized queries for filtering results." | ||
| 125 | } | ||
| 126 | |||
| 91 | // Build server capabilities - don't fetch actual tools/resources during init | 127 | // Build server capabilities - don't fetch actual tools/resources during init |
| 92 | // Tools and resources will be discovered via separate list requests per MCP spec | 128 | // Tools and resources will be discovered via separate list requests per MCP spec |
| 93 | def serverCapabilities = [ | 129 | def serverCapabilities = [ |
| ... | @@ -107,7 +143,7 @@ | ... | @@ -107,7 +143,7 @@ |
| 107 | capabilities: serverCapabilities, | 143 | capabilities: serverCapabilities, |
| 108 | serverInfo: serverInfo, | 144 | serverInfo: serverInfo, |
| 109 | sessionId: sessionId, | 145 | sessionId: sessionId, |
| 110 | instructions: "This server provides access to Moqui ERP through MCP. For common business queries: Use PopCommerce.PopCommerceAdmin.Catalog.Feature.FindFeature to search by features like color or size. Use PopCommerce.PopCommerceAdmin.Catalog.Product.FindProduct for product catalog, PopCommerce.PopCommerceAdmin.Order.FindOrder for order status, PopCommerce.PopCommerceRoot.Customer for customer management, PopCommerce.PopCommerceAdmin.Catalog.Product.EditPrices to check prices and PopCommerce.PopCommerceAdmin.QuickSearch for general searches. All screens support parameterized queries for filtering results." | 146 | instructions: instructions |
| 111 | ] | 147 | ] |
| 112 | 148 | ||
| 113 | ec.logger.info("MCP Initialize for user ${userId} (session ${sessionId}): capabilities negotiated") | 149 | ec.logger.info("MCP Initialize for user ${userId} (session ${sessionId}): capabilities negotiated") |
| ... | @@ -353,11 +389,43 @@ | ... | @@ -353,11 +389,43 @@ |
| 353 | 389 | ||
| 354 | // Handle special moqui://mcp/instructions resource | 390 | // Handle special moqui://mcp/instructions resource |
| 355 | if (uri == "moqui://mcp/instructions") { | 391 | if (uri == "moqui://mcp/instructions") { |
| 392 | // Try to load from wiki | ||
| 393 | def instructionsText = null | ||
| 394 | try { | ||
| 395 | def wikiPage = ec.entity.find("moqui.resource.wiki.WikiPage") | ||
| 396 | .condition("wikiSpaceId", "MCP_SCREEN_DOCS") | ||
| 397 | .condition("pagePath", "root") | ||
| 398 | .useCache(true) | ||
| 399 | .one() | ||
| 400 | |||
| 401 | if (wikiPage) { | ||
| 402 | def wikiSpace = ec.entity.find("moqui.resource.wiki.WikiSpace") | ||
| 403 | .condition("wikiSpaceId", wikiPage.wikiSpaceId) | ||
| 404 | .one() | ||
| 405 | |||
| 406 | if (wikiSpace) { | ||
| 407 | def pageLocation = wikiSpace.rootPageLocation | ||
| 408 | if (!pageLocation.endsWith('/')) pageLocation += '/' | ||
| 409 | pageLocation += wikiPage.pagePath + '.md' | ||
| 410 | |||
| 411 | def pageRef = ec.resource.getLocationReference(pageLocation) | ||
| 412 | instructionsText = pageRef?.getText() | ||
| 413 | } | ||
| 414 | } | ||
| 415 | } catch (Exception e) { | ||
| 416 | ec.logger.debug("Could not load instructions from wiki: ${e.message}") | ||
| 417 | } | ||
| 418 | |||
| 419 | // Fallback to hardcoded instructions | ||
| 420 | if (!instructionsText) { | ||
| 421 | instructionsText = "This server provides access to Moqui ERP through MCP. For common business queries: Use PopCommerce.PopCommerceAdmin.Catalog.Feature.FindFeature to search by features like color or size. Use PopCommerce.PopCommerceAdmin.Catalog.Product.FindProduct for product catalog, PopCommerce.PopCommerceAdmin.Order.FindOrder for order status, PopCommerce.PopCommerceRoot.Customer for customer management, PopCommerce.PopCommerceAdmin.Catalog.Product.EditPrices to check prices and PopCommerce.PopCommerceAdmin.QuickSearch for general searches. All screens support parameterized queries for filtering results." | ||
| 422 | } | ||
| 423 | |||
| 356 | result = [ | 424 | result = [ |
| 357 | content: [[ | 425 | content: [[ |
| 358 | uri: "moqui://mcp/instructions", | 426 | uri: "moqui://mcp/instructions", |
| 359 | mimeType: "text/plain", | 427 | mimeType: "text/plain", |
| 360 | text: "This server provides access to Moqui ERP through MCP. For common business queries: Use PopCommerce.PopCommerceAdmin.Catalog.Feature.FindFeature to search by features like color or size. Use PopCommerce.PopCommerceAdmin.Catalog.Product.FindProduct for product catalog, PopCommerce.PopCommerceAdmin.Order.FindOrder for order status, PopCommerce.PopCommerceRoot.Customer for customer management, PopCommerce.PopCommerceAdmin.Catalog.Product.EditPrices to check prices and PopCommerce.PopCommerceAdmin.QuickSearch for general searches. All screens support parameterized queries for filtering results." | 428 | text: instructionsText |
| 361 | ]], | 429 | ]], |
| 362 | isError: false | 430 | isError: false |
| 363 | ] | 431 | ] |
| ... | @@ -653,10 +721,68 @@ ExecutionContext ec = context.ec | ... | @@ -653,10 +721,68 @@ ExecutionContext ec = context.ec |
| 653 | 721 | ||
| 654 | def startTime = System.currentTimeMillis() | 722 | def startTime = System.currentTimeMillis() |
| 655 | 723 | ||
| 656 | // Set parameters in context | 724 | // Set parameters in context |
| 657 | if (parameters) { | 725 | if (parameters) { |
| 658 | ec.context.putAll(parameters) | 726 | ec.context.putAll(parameters) |
| 727 | } | ||
| 728 | |||
| 729 | // Helper function to get simple path from component path | ||
| 730 | def getSimplePath = { fullPath -> | ||
| 731 | if (!fullPath || fullPath == "root") return "root" | ||
| 732 | String cleanPath = fullPath | ||
| 733 | if (cleanPath.startsWith("component://")) cleanPath = cleanPath.substring(12) | ||
| 734 | if (cleanPath.endsWith(".xml")) cleanPath = cleanPath.substring(0, cleanPath.length() - 4) | ||
| 735 | List<String> parts = cleanPath.split('/').toList() | ||
| 736 | if (parts.size() > 1 && parts[1] == "screen") parts.remove(1) | ||
| 737 | return parts.join('.') | ||
| 738 | } | ||
| 739 | |||
| 740 | // Helper function to load wiki instructions for a screen | ||
| 741 | def getWikiInstructions = { screenPath -> | ||
| 742 | try { | ||
| 743 | def wikiPage = ec.entity.find("moqui.resource.wiki.WikiPage") | ||
| 744 | .condition("wikiSpaceId", "MCP_SCREEN_DOCS") | ||
| 745 | .condition("pagePath", screenPath) | ||
| 746 | .useCache(true) | ||
| 747 | .one() | ||
| 748 | |||
| 749 | if (!wikiPage) return null | ||
| 750 | |||
| 751 | def wikiSpace = ec.entity.find("moqui.resource.wiki.WikiSpace") | ||
| 752 | .condition("wikiSpaceId", wikiPage.wikiSpaceId) | ||
| 753 | .one() | ||
| 754 | |||
| 755 | if (!wikiSpace) return null | ||
| 756 | |||
| 757 | // Build the resource location for the page | ||
| 758 | def pageLocation = wikiSpace.rootPageLocation | ||
| 759 | if (!pageLocation.endsWith('/')) { | ||
| 760 | pageLocation += '/' | ||
| 761 | } | ||
| 762 | pageLocation += wikiPage.pagePath + '.md' | ||
| 763 | |||
| 764 | // Get the resource reference and text content | ||
| 765 | def pageRef = ec.resource.getLocationReference(pageLocation) | ||
| 766 | def wikiText = pageRef?.getText() | ||
| 767 | |||
| 768 | if (wikiText) { | ||
| 769 | return wikiText | ||
| 770 | } | ||
| 771 | } catch (Exception e) { | ||
| 772 | ec.logger.debug("Could not load wiki instructions for ${screenPath}: ${e.message}") | ||
| 659 | } | 773 | } |
| 774 | return null | ||
| 775 | } | ||
| 776 | |||
| 777 | // Resolve input screen path to simple path for lookup | ||
| 778 | def inputScreenPath = screenPath | ||
| 779 | if (screenPath.startsWith("component://")) { | ||
| 780 | inputScreenPath = getSimplePath(screenPath) | ||
| 781 | } | ||
| 782 | ec.logger.info("MCP Screen Execution: Looking up wiki docs for ${inputScreenPath}") | ||
| 783 | |||
| 784 | // Try to get wiki instructions | ||
| 785 | def wikiInstructions = getWikiInstructions(inputScreenPath) | ||
| 660 | 786 | ||
| 661 | // Check if action is being processed - use real screen rendering if so | 787 | // Check if action is being processed - use real screen rendering if so |
| 662 | def isActionExecution = parameters?.action != null | 788 | def isActionExecution = parameters?.action != null |
| ... | @@ -833,6 +959,7 @@ def startTime = System.currentTimeMillis() | ... | @@ -833,6 +959,7 @@ def startTime = System.currentTimeMillis() |
| 833 | if (mcpData.forms) mcpResult.forms = mcpData.forms | 959 | if (mcpData.forms) mcpResult.forms = mcpData.forms |
| 834 | if (mcpData.actions) mcpResult.actions = mcpData.actions | 960 | if (mcpData.actions) mcpResult.actions = mcpData.actions |
| 835 | if (output) mcpResult.htmlPreview = output.take(2000) + (output.length() > 2000 ? "..." : "") | 961 | if (output) mcpResult.htmlPreview = output.take(2000) + (output.length() > 2000 ? "..." : "") |
| 962 | if (wikiInstructions) mcpResult.wikiInstructions = wikiInstructions | ||
| 836 | 963 | ||
| 837 | content << [ | 964 | content << [ |
| 838 | type: "text", | 965 | type: "text", |
| ... | @@ -840,9 +967,13 @@ def startTime = System.currentTimeMillis() | ... | @@ -840,9 +967,13 @@ def startTime = System.currentTimeMillis() |
| 840 | ] | 967 | ] |
| 841 | } else { | 968 | } else { |
| 842 | // Return raw output for other modes | 969 | // Return raw output for other modes |
| 970 | def textOutput = output | ||
| 971 | if (wikiInstructions) { | ||
| 972 | textOutput = "--- Wiki Instructions ---\n\n${wikiInstructions}\n\n--- Screen Output ---\n\n${output}" | ||
| 973 | } | ||
| 843 | content << [ | 974 | content << [ |
| 844 | type: "text", | 975 | type: "text", |
| 845 | text: output, | 976 | text: textOutput, |
| 846 | screenPath: screenPath, | 977 | screenPath: screenPath, |
| 847 | screenUrl: screenUrl, | 978 | screenUrl: screenUrl, |
| 848 | executionTime: executionTime, | 979 | executionTime: executionTime, |
| ... | @@ -1155,6 +1286,73 @@ def startTime = System.currentTimeMillis() | ... | @@ -1155,6 +1286,73 @@ def startTime = System.currentTimeMillis() |
| 1155 | currentPath = currentPath.split("\\?")[0] | 1286 | currentPath = currentPath.split("\\?")[0] |
| 1156 | } | 1287 | } |
| 1157 | 1288 | ||
| 1289 | // Helper function to load wiki content | ||
| 1290 | def loadWikiContent = { path -> | ||
| 1291 | ec.logger.info("BrowseScreens: loadWikiContent CALLED for ${path}") | ||
| 1292 | try { | ||
| 1293 | def simplePath = (path == "root") ? "root" : path | ||
| 1294 | if (simplePath.contains("?")) { | ||
| 1295 | simplePath = simplePath.split("\\?")[0] | ||
| 1296 | } | ||
| 1297 | |||
| 1298 | ec.logger.info("BrowseScreens: Looking up wiki instructions for ${simplePath}") | ||
| 1299 | |||
| 1300 | def wikiPage = ec.entity.find("moqui.resource.wiki.WikiPage") | ||
| 1301 | .condition("wikiSpaceId", "MCP_SCREEN_DOCS") | ||
| 1302 | .condition("pagePath", simplePath) | ||
| 1303 | .useCache(true) | ||
| 1304 | .one() | ||
| 1305 | |||
| 1306 | if (wikiPage) { | ||
| 1307 | ec.logger.info("BrowseScreens: Found wikiPage: ${wikiPage.pagePath}") | ||
| 1308 | def wikiSpace = ec.entity.find("moqui.resource.wiki.WikiSpace") | ||
| 1309 | .condition("wikiSpaceId", wikiPage.wikiSpaceId) | ||
| 1310 | .one() | ||
| 1311 | |||
| 1312 | if (wikiSpace) { | ||
| 1313 | ec.logger.info("BrowseScreens: Found wikiSpace: ${wikiSpace.wikiSpaceId}") | ||
| 1314 | |||
| 1315 | def dbResource = ec.entity.find("moqui.resource.DbResource") | ||
| 1316 | .condition("parentResourceId", "WIKI_MCP_SCREEN_DOCS") | ||
| 1317 | .condition("filename", wikiPage.pagePath + ".md") | ||
| 1318 | .one() | ||
| 1319 | |||
| 1320 | if (dbResource) { | ||
| 1321 | ec.logger.info("BrowseScreens: Found dbResource: ${dbResource.resourceId}") | ||
| 1322 | def dbResourceFile = ec.entity.find("moqui.resource.DbResourceFile") | ||
| 1323 | .condition("resourceId", dbResource.resourceId) | ||
| 1324 | .condition("versionName", wikiPage.publishedVersionName) | ||
| 1325 | .one() | ||
| 1326 | |||
| 1327 | ec.logger.info("BrowseScreens: dbResourceFile query result: ${dbResourceFile ? 'found' : 'null'}") | ||
| 1328 | |||
| 1329 | if (!dbResourceFile) { | ||
| 1330 | dbResourceFile = ec.entity.find("moqui.resource.DbResourceFile") | ||
| 1331 | .condition("resourceId", dbResource.resourceId) | ||
| 1332 | .one() | ||
| 1333 | ec.logger.info("BrowseScreens: dbResourceFile fallback query result: ${dbResourceFile ? 'found' : 'null'}") | ||
| 1334 | } | ||
| 1335 | |||
| 1336 | if (dbResourceFile) { | ||
| 1337 | ec.logger.info("BrowseScreens: dbResourceFile.fileData: ${dbResourceFile.fileData ? 'exists, size=' + dbResourceFile.fileData.length : 'null'}") | ||
| 1338 | } | ||
| 1339 | |||
| 1340 | if (dbResourceFile && dbResourceFile.fileData) { | ||
| 1341 | def content = new String(dbResourceFile.fileData, "UTF-8") | ||
| 1342 | ec.logger.info("BrowseScreens: Found wiki instructions for ${simplePath}, length: ${content?.length()}") | ||
| 1343 | return content | ||
| 1344 | } | ||
| 1345 | } else { | ||
| 1346 | ec.logger.warn("BrowseScreens: No dbResource found for ${wikiPage.pagePath}.md") | ||
| 1347 | } | ||
| 1348 | } | ||
| 1349 | } | ||
| 1350 | } catch (Exception e) { | ||
| 1351 | ec.logger.warn("BrowseScreens: Error getting wiki instructions: ${e.message}") | ||
| 1352 | } | ||
| 1353 | return null | ||
| 1354 | } | ||
| 1355 | |||
| 1158 | // Helper to convert full component path to simple path (PopCommerce/screen/Root.xml -> PopCommerce.Root) | 1356 | // Helper to convert full component path to simple path (PopCommerce/screen/Root.xml -> PopCommerce.Root) |
| 1159 | def convertToSimplePath = { fullPath -> | 1357 | def convertToSimplePath = { fullPath -> |
| 1160 | if (!fullPath) return null | 1358 | if (!fullPath) return null |
| ... | @@ -1166,6 +1364,18 @@ def startTime = System.currentTimeMillis() | ... | @@ -1166,6 +1364,18 @@ def startTime = System.currentTimeMillis() |
| 1166 | return parts.join('.') | 1364 | return parts.join('.') |
| 1167 | } | 1365 | } |
| 1168 | 1366 | ||
| 1367 | // Helper to extract short description from wiki content | ||
| 1368 | def getShortDescription = { wikiText -> | ||
| 1369 | if (!wikiText) return null | ||
| 1370 | def lines = wikiText.split('\n') | ||
| 1371 | for (def line : lines) { | ||
| 1372 | if (line.trim() && !line.trim().startsWith('#')) { | ||
| 1373 | return line.trim().take(200) | ||
| 1374 | } | ||
| 1375 | } | ||
| 1376 | return null | ||
| 1377 | } | ||
| 1378 | |||
| 1169 | if (currentPath == "root") { | 1379 | if (currentPath == "root") { |
| 1170 | // Discover top-level applications | 1380 | // Discover top-level applications |
| 1171 | def aacvList = ec.entity.find("moqui.security.ArtifactAuthzCheckView") | 1381 | def aacvList = ec.entity.find("moqui.security.ArtifactAuthzCheckView") |
| ... | @@ -1194,9 +1404,11 @@ def startTime = System.currentTimeMillis() | ... | @@ -1194,9 +1404,11 @@ def startTime = System.currentTimeMillis() |
| 1194 | 1404 | ||
| 1195 | for (def screenPath in rootScreens) { | 1405 | for (def screenPath in rootScreens) { |
| 1196 | def simplePath = convertToSimplePath(screenPath) | 1406 | def simplePath = convertToSimplePath(screenPath) |
| 1407 | def wikiContent = loadWikiContent(simplePath) | ||
| 1408 | def description = wikiContent ? getShortDescription(wikiContent) : "Application: ${simplePath}" | ||
| 1197 | subscreens << [ | 1409 | subscreens << [ |
| 1198 | path: simplePath, | 1410 | path: simplePath, |
| 1199 | description: "Application: ${simplePath}" | 1411 | description: description |
| 1200 | ] | 1412 | ] |
| 1201 | } | 1413 | } |
| 1202 | } else { | 1414 | } else { |
| ... | @@ -1238,9 +1450,11 @@ def startTime = System.currentTimeMillis() | ... | @@ -1238,9 +1450,11 @@ def startTime = System.currentTimeMillis() |
| 1238 | for (subItem in subItems) { | 1450 | for (subItem in subItems) { |
| 1239 | def subName = subItem.getName() | 1451 | def subName = subItem.getName() |
| 1240 | def subPath = currentPath + "." + subName | 1452 | def subPath = currentPath + "." + subName |
| 1453 | def wikiContent = loadWikiContent(subPath) | ||
| 1454 | def description = wikiContent ? getShortDescription(wikiContent) : "Subscreen: ${subName}" | ||
| 1241 | subscreens << [ | 1455 | subscreens << [ |
| 1242 | path: subPath, | 1456 | path: subPath, |
| 1243 | description: "Subscreen: ${subName}" | 1457 | description: description |
| 1244 | ] | 1458 | ] |
| 1245 | } | 1459 | } |
| 1246 | } | 1460 | } |
| ... | @@ -1375,6 +1589,13 @@ def startTime = System.currentTimeMillis() | ... | @@ -1375,6 +1589,13 @@ def startTime = System.currentTimeMillis() |
| 1375 | } | 1589 | } |
| 1376 | } | 1590 | } |
| 1377 | 1591 | ||
| 1592 | // Try to get wiki instructions for screen | ||
| 1593 | def wikiInstructions = null | ||
| 1594 | |||
| 1595 | ec.logger.info("BrowseScreens: About to check wiki instructions, currentPath='${currentPath}', isRoot=${currentPath == 'root'}") | ||
| 1596 | |||
| 1597 | wikiInstructions = loadWikiContent(currentPath) | ||
| 1598 | |||
| 1378 | // Render current screen if not root browsing | 1599 | // Render current screen if not root browsing |
| 1379 | def renderedContent = null | 1600 | def renderedContent = null |
| 1380 | def renderError = null | 1601 | def renderError = null |
| ... | @@ -1468,6 +1689,10 @@ def startTime = System.currentTimeMillis() | ... | @@ -1468,6 +1689,10 @@ def startTime = System.currentTimeMillis() |
| 1468 | resultMap.renderedContent = renderedContent | 1689 | resultMap.renderedContent = renderedContent |
| 1469 | } | 1690 | } |
| 1470 | 1691 | ||
| 1692 | if (wikiInstructions) { | ||
| 1693 | resultMap.wikiInstructions = wikiInstructions | ||
| 1694 | } | ||
| 1695 | |||
| 1471 | if (renderError) { | 1696 | if (renderError) { |
| 1472 | resultMap.renderError = renderError | 1697 | resultMap.renderError = renderError |
| 1473 | } | 1698 | } | ... | ... |
-
Please register or sign in to post a comment