WIP: Add SDK-based MCP servlet implementations with SSE support
- Add multiple servlet implementations (EnhancedMcpServlet, ServiceBasedMcpServlet, MoquiMcpServlet) - Implement SSE servlet support with proper content-type handling - Add MCP filter for request processing - Add web.xml configuration for servlet deployment - Include SDK framework JAR and configuration files - Remove old screen-based MCP implementation - Update component configuration for new servlet-based approach
Showing
26 changed files
with
500 additions
and
37 deletions
.gradle/8.9/checksums/checksums.lock
0 → 100644
No preview for this file type
File mode changed
.gradle/8.9/fileChanges/last-build.bin
0 → 100644
No preview for this file type
.gradle/8.9/fileHashes/fileHashes.lock
0 → 100644
No preview for this file type
.gradle/8.9/gc.properties
0 → 100644
File mode changed
No preview for this file type
.gradle/buildOutputCleanup/cache.properties
0 → 100644
.gradle/vcs-1/gc.properties
0 → 100644
File mode changed
.settings/org.eclipse.buildship.core.prefs
0 → 100644
| 1 | arguments=--init-script /home/ean/.config/Code/User/globalStorage/redhat.java/1.46.0/config_linux/org.eclipse.osgi/58/0/.cp/gradle/init/init.gradle --init-script /home/ean/.config/Code/User/globalStorage/redhat.java/1.46.0/config_linux/org.eclipse.osgi/58/0/.cp/gradle/protobuf/init.gradle | ||
| 2 | auto.sync=false | ||
| 3 | build.scans.enabled=false | ||
| 4 | connection.gradle.distribution=GRADLE_DISTRIBUTION(VERSION(8.9)) | ||
| 5 | connection.project.dir=../../.. | ||
| 6 | eclipse.preferences.version=1 | ||
| 7 | gradle.user.home= | ||
| 8 | java.home=/usr/lib/jvm/java-17-openjdk-amd64 | ||
| 9 | jvm.arguments= | ||
| 10 | offline.mode=false | ||
| 11 | override.workspace.settings=true | ||
| 12 | show.console.view=true | ||
| 13 | show.executions.view=true |
README-SDK-Services.md
0 → 100644
This diff is collapsed.
Click to expand it.
README-SDK-Servlet.md
0 → 100644
This diff is collapsed.
Click to expand it.
README-SSE-Servlet.md
0 → 100644
This diff is collapsed.
Click to expand it.
build.gradle
0 → 100644
| 1 | /* | ||
| 2 | * This software is in the public domain under CC0 1.0 Universal plus a | ||
| 3 | * Grant of Patent License. | ||
| 4 | * | ||
| 5 | * To the extent possible under law, the author(s) have dedicated all | ||
| 6 | * copyright and related and neighboring rights to this software to the | ||
| 7 | * public domain worldwide. This software is distributed without any | ||
| 8 | * warranty. | ||
| 9 | * | ||
| 10 | * You should have received a copy of the CC0 Public Domain Dedication | ||
| 11 | * along with this software (see the LICENSE.md file). If not, see | ||
| 12 | * <http://creativecommons.org/publicdomain/zero/1.0/>. | ||
| 13 | */ | ||
| 14 | |||
| 15 | apply plugin: 'groovy' | ||
| 16 | |||
| 17 | def componentNode = parseComponent(project) | ||
| 18 | version = componentNode.'@version' | ||
| 19 | def jarBaseName = componentNode.'@name' | ||
| 20 | def moquiDir = projectDir.parentFile.parentFile.parentFile | ||
| 21 | def frameworkDir = file(moquiDir.absolutePath + '/framework') | ||
| 22 | |||
| 23 | repositories { | ||
| 24 | flatDir name: 'localLib', dirs: frameworkDir.absolutePath + '/lib' | ||
| 25 | mavenCentral() | ||
| 26 | } | ||
| 27 | |||
| 28 | // Log4J has annotation processors, disable to avoid warning | ||
| 29 | tasks.withType(JavaCompile) { options.compilerArgs << "-proc:none" } | ||
| 30 | tasks.withType(GroovyCompile) { options.compilerArgs << "-proc:none" } | ||
| 31 | |||
| 32 | dependencies { | ||
| 33 | implementation project(':framework') | ||
| 34 | |||
| 35 | // Servlet API (provided by framework, but needed for compilation) | ||
| 36 | compileOnly 'javax.servlet:javax.servlet-api:4.0.1' | ||
| 37 | } | ||
| 38 | |||
| 39 | // by default the Java plugin runs test on build, change to not do that (only run test if explicit task) | ||
| 40 | check.dependsOn.clear() | ||
| 41 | |||
| 42 | task cleanLib(type: Delete) { delete fileTree(dir: projectDir.absolutePath+'/lib', include: '*') } | ||
| 43 | clean.dependsOn cleanLib | ||
| 44 | |||
| 45 | jar { | ||
| 46 | destinationDirectory = file(projectDir.absolutePath + '/lib') | ||
| 47 | archiveBaseName = jarBaseName | ||
| 48 | } | ||
| 49 | task copyDependencies { doLast { | ||
| 50 | copy { from (configurations.runtimeClasspath - project(':framework').configurations.runtimeClasspath) | ||
| 51 | into file(projectDir.absolutePath + '/lib') } | ||
| 52 | } } | ||
| 53 | copyDependencies.dependsOn cleanLib | ||
| 54 | jar.dependsOn copyDependencies | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file |
| ... | @@ -14,13 +14,49 @@ | ... | @@ -14,13 +14,49 @@ |
| 14 | xsi:noNamespaceSchemaLocation="http://moqui.org/xsd/component-definition-3.xsd" | 14 | xsi:noNamespaceSchemaLocation="http://moqui.org/xsd/component-definition-3.xsd" |
| 15 | name="moqui-mcp-2"> | 15 | name="moqui-mcp-2"> |
| 16 | 16 | ||
| 17 | <!-- No dependencies - uses only core framework --> | 17 | |
| 18 | |||
| 19 | <!-- MCP SDK dependencies --> | ||
| 20 | <dependency> | ||
| 21 | <groupId>io.modelcontextprotocol.sdk</groupId> | ||
| 22 | <artifactId>mcp</artifactId> | ||
| 23 | <version>0.16.0</version> | ||
| 24 | </dependency> | ||
| 25 | <dependency> | ||
| 26 | <groupId>io.modelcontextprotocol.sdk</groupId> | ||
| 27 | <artifactId>mcp-core</artifactId> | ||
| 28 | <version>0.16.0</version> | ||
| 29 | </dependency> | ||
| 30 | <dependency> | ||
| 31 | <groupId>com.fasterxml.jackson.core</groupId> | ||
| 32 | <artifactId>jackson-databind</artifactId> | ||
| 33 | <version>2.15.2</version> | ||
| 34 | </dependency> | ||
| 35 | <dependency> | ||
| 36 | <groupId>com.fasterxml.jackson.core</groupId> | ||
| 37 | <artifactId>jackson-core</artifactId> | ||
| 38 | <version>2.15.2</version> | ||
| 39 | </dependency> | ||
| 40 | <dependency> | ||
| 41 | <groupId>io.projectreactor</groupId> | ||
| 42 | <artifactId>reactor-core</artifactId> | ||
| 43 | <version>3.5.10</version> | ||
| 44 | </dependency> | ||
| 18 | 45 | ||
| 19 | <entity-factory load-path="entity/" /> | 46 | <entity-factory load-path="entity/" /> |
| 20 | <service-factory load-path="service/" /> | 47 | <service-factory load-path="service/" /> |
| 21 | <screen-factory load-path="screen/" /> | 48 | <!-- <screen-factory load-path="screen/" /> --> |
| 22 | 49 | ||
| 23 | <!-- Load seed data --> | 50 | <!-- Load seed data --> |
| 24 | <entity-factory load-data="data/McpSecuritySeedData.xml" /> | 51 | <entity-factory load-data="data/McpSecuritySeedData.xml" /> |
| 52 | |||
| 53 | <!-- Register MCP filter | ||
| 54 | <webapp-list> | ||
| 55 | <webapp name="webroot"> | ||
| 56 | <filter name="McpFilter" class="org.moqui.mcp.McpFilter"> | ||
| 57 | <url-pattern>/mcpservlet/*</url-pattern> | ||
| 58 | </filter> | ||
| 59 | </webapp> | ||
| 60 | </webapp-list> --> | ||
| 25 | 61 | ||
| 26 | </component> | 62 | </component> | ... | ... |
lib/moqui-framework-3.1.0-rc2.jar
0 → 100644
No preview for this file type
screen/webroot/mcp.xml
deleted
100644 → 0
This diff is collapsed.
Click to expand it.
| ... | @@ -257,10 +257,14 @@ | ... | @@ -257,10 +257,14 @@ |
| 257 | def userId = ec.user.userId | 257 | def userId = ec.user.userId |
| 258 | def userAccountId = userId ? userId : null | 258 | def userAccountId = userId ? userId : null |
| 259 | 259 | ||
| 260 | // Build server capabilities | 260 | // Get user-specific tools and resources |
| 261 | def toolsResult = ec.service.sync().name("org.moqui.mcp.McpServices.mcp#ToolsList").parameters([:]).call() | ||
| 262 | def resourcesResult = ec.service.sync().name("org.moqui.mcp.McpServices.mcp#ResourcesList").parameters([:]).call() | ||
| 263 | |||
| 264 | // Build server capabilities based on what user can access | ||
| 261 | def serverCapabilities = [ | 265 | def serverCapabilities = [ |
| 262 | tools: [:], | 266 | tools: toolsResult?.result?.tools ? [listChanged: true] : [:], |
| 263 | resources: [:], | 267 | resources: resourcesResult?.result?.resources ? [subscribe: true, listChanged: true] : [:], |
| 264 | logging: [:] | 268 | logging: [:] |
| 265 | ] | 269 | ] |
| 266 | 270 | ||
| ... | @@ -274,8 +278,10 @@ | ... | @@ -274,8 +278,10 @@ |
| 274 | protocolVersion: "2025-06-18", | 278 | protocolVersion: "2025-06-18", |
| 275 | capabilities: serverCapabilities, | 279 | capabilities: serverCapabilities, |
| 276 | serverInfo: serverInfo, | 280 | serverInfo: serverInfo, |
| 277 | instructions: "This server provides access to Moqui ERP services and entities through MCP. Use tools/list to discover available operations." | 281 | instructions: "This server provides access to Moqui ERP services and entities through MCP. Tools and resources are filtered based on your permissions." |
| 278 | ] | 282 | ] |
| 283 | |||
| 284 | ec.logger.info("MCP Initialize for user ${userId}: ${toolsResult?.result?.tools?.size() ?: 0} tools, ${resourcesResult?.result?.resources?.size() ?: 0} resources") | ||
| 279 | ]]></script> | 285 | ]]></script> |
| 280 | </actions> | 286 | </actions> |
| 281 | </service> | 287 | </service> |
| ... | @@ -321,13 +327,27 @@ | ... | @@ -321,13 +327,27 @@ |
| 321 | ] | 327 | ] |
| 322 | ] | 328 | ] |
| 323 | 329 | ||
| 330 | // Add service metadata to help LLM | ||
| 331 | if (serviceInfo.verb && serviceInfo.noun) { | ||
| 332 | tool.description += " (${serviceInfo.verb}:${serviceInfo.noun})" | ||
| 333 | } | ||
| 334 | |||
| 324 | // Convert service parameters to JSON Schema | 335 | // Convert service parameters to JSON Schema |
| 325 | def inParamNames = serviceInfo.getInParameterNames() | 336 | def inParamNames = serviceInfo.getInParameterNames() |
| 326 | for (paramName in inParamNames) { | 337 | for (paramName in inParamNames) { |
| 327 | def paramInfo = serviceInfo.getInParameter(paramName) | 338 | def paramInfo = serviceInfo.getInParameter(paramName) |
| 339 | def paramDesc = paramInfo.description ?: "" | ||
| 340 | |||
| 341 | // Add type information to description for LLM | ||
| 342 | if (!paramDesc) { | ||
| 343 | paramDesc = "Parameter of type ${paramInfo.type}" | ||
| 344 | } else { | ||
| 345 | paramDesc += " (type: ${paramInfo.type})" | ||
| 346 | } | ||
| 347 | |||
| 328 | tool.inputSchema.properties[paramName] = [ | 348 | tool.inputSchema.properties[paramName] = [ |
| 329 | type: convertMoquiTypeToJsonSchemaType(paramInfo.type), | 349 | type: convertMoquiTypeToJsonSchemaType(paramInfo.type), |
| 330 | description: paramInfo.description ?: "" | 350 | description: paramDesc |
| 331 | ] | 351 | ] |
| 332 | 352 | ||
| 333 | if (paramInfo.required) { | 353 | if (paramInfo.required) { |
| ... | @@ -474,10 +494,15 @@ | ... | @@ -474,10 +494,15 @@ |
| 474 | def resource = [ | 494 | def resource = [ |
| 475 | uri: "entity://${entityName}", | 495 | uri: "entity://${entityName}", |
| 476 | name: entityName, | 496 | name: entityName, |
| 477 | description: "Moqui entity: ${entityName}", | 497 | description: entityInfo.description ?: "Moqui entity: ${entityName}", |
| 478 | mimeType: "application/json" | 498 | mimeType: "application/json" |
| 479 | ] | 499 | ] |
| 480 | 500 | ||
| 501 | // Add entity metadata to help LLM | ||
| 502 | if (entityInfo.packageName) { | ||
| 503 | resource.description += " (package: ${entityInfo.packageName})" | ||
| 504 | } | ||
| 505 | |||
| 481 | availableResources << resource | 506 | availableResources << resource |
| 482 | 507 | ||
| 483 | } catch (Exception e) { | 508 | } catch (Exception e) { |
| ... | @@ -536,6 +561,9 @@ | ... | @@ -536,6 +561,9 @@ |
| 536 | 561 | ||
| 537 | def startTime = System.currentTimeMillis() | 562 | def startTime = System.currentTimeMillis() |
| 538 | try { | 563 | try { |
| 564 | // Get entity definition for field descriptions | ||
| 565 | def entityDef = ec.entity.getEntityDefinition(entityName) | ||
| 566 | |||
| 539 | // Query entity data (limited to prevent large responses) | 567 | // Query entity data (limited to prevent large responses) |
| 540 | def entityList = ec.entity.find(entityName) | 568 | def entityList = ec.entity.find(entityName) |
| 541 | .limit(100) | 569 | .limit(100) |
| ... | @@ -543,6 +571,18 @@ | ... | @@ -543,6 +571,18 @@ |
| 543 | 571 | ||
| 544 | def executionTime = (System.currentTimeMillis() - startTime) / 1000.0 | 572 | def executionTime = (System.currentTimeMillis() - startTime) / 1000.0 |
| 545 | 573 | ||
| 574 | // Build field info for LLM | ||
| 575 | def fieldInfo = [] | ||
| 576 | entityDef.allFieldInfoList.each { field -> | ||
| 577 | fieldInfo << [ | ||
| 578 | name: field.name, | ||
| 579 | type: field.type, | ||
| 580 | description: field.description ?: "", | ||
| 581 | isPk: field.isPk, | ||
| 582 | required: field.notNull | ||
| 583 | ] | ||
| 584 | } | ||
| 585 | |||
| 546 | // Convert to MCP resource content | 586 | // Convert to MCP resource content |
| 547 | def contents = [ | 587 | def contents = [ |
| 548 | [ | 588 | [ |
| ... | @@ -550,7 +590,10 @@ | ... | @@ -550,7 +590,10 @@ |
| 550 | mimeType: "application/json", | 590 | mimeType: "application/json", |
| 551 | text: new JsonBuilder([ | 591 | text: new JsonBuilder([ |
| 552 | entityName: entityName, | 592 | entityName: entityName, |
| 593 | description: entityDef.description ?: "", | ||
| 594 | packageName: entityDef.packageName, | ||
| 553 | recordCount: entityList.size(), | 595 | recordCount: entityList.size(), |
| 596 | fields: fieldInfo, | ||
| 554 | data: entityList | 597 | data: entityList |
| 555 | ]).toString() | 598 | ]).toString() |
| 556 | ] | 599 | ] | ... | ... |
service/mcp.rest.xml
deleted
100644 → 0
| 1 | <?xml version="1.0" encoding="UTF-8"?> | ||
| 2 | <!-- This software is in the public domain under CC0 1.0 Universal plus a | ||
| 3 | Grant of Patent License. | ||
| 4 | |||
| 5 | To the extent possible under law, author(s) have dedicated all | ||
| 6 | copyright and related and neighboring rights to this software to the | ||
| 7 | public domain worldwide. This software is distributed without any warranty. | ||
| 8 | |||
| 9 | You should have received a copy of the CC0 Public Domain Dedication | ||
| 10 | along with this software (see the LICENSE.md file). If not, see | ||
| 11 | <https://creativecommons.org/publicdomain/zero/1.0/>. --> | ||
| 12 | |||
| 13 | <resource xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://moqui.org/xsd/rest-api-3.xsd" | ||
| 14 | name="mcp" displayName="MCP API" version="2.0.0" | ||
| 15 | description="MCP API services for Moqui integration - NOTE: Main functionality moved to screen/webapp.xml"> | ||
| 16 | |||
| 17 | <!-- NOTE: Main MCP functionality moved to screen/webapp.xml for unified JSON-RPC and SSE handling --> | ||
| 18 | <!-- Keeping only basic GET endpoints for health checks and debugging --> | ||
| 19 | |||
| 20 | <resource name="rpc"> | ||
| 21 | <method type="get"> | ||
| 22 | <service name="McpServices.mcp#Ping"/> | ||
| 23 | </method> | ||
| 24 | <method type="get" path="debug"> | ||
| 25 | <service name="McpServices.debug#ComponentStatus"/> | ||
| 26 | </method> | ||
| 27 | </resource> | ||
| 28 | |||
| 29 | </resource> |
This diff is collapsed.
Click to expand it.
| 1 | /* | ||
| 2 | * This software is in the public domain under CC0 1.0 Universal plus a | ||
| 3 | * Grant of Patent License. | ||
| 4 | * | ||
| 5 | * To the extent possible under law, author(s) have dedicated all | ||
| 6 | * copyright and related and neighboring rights to this software to the | ||
| 7 | * public domain worldwide. This software is distributed without any | ||
| 8 | * warranty. | ||
| 9 | * | ||
| 10 | * You should have received a copy of the CC0 Public Domain Dedication | ||
| 11 | * along with this software (see the LICENSE.md file). If not, see | ||
| 12 | * <http://creativecommons.org/publicdomain/zero/1.0/>. | ||
| 13 | */ | ||
| 14 | package org.moqui.mcp | ||
| 15 | |||
| 16 | import org.slf4j.Logger | ||
| 17 | import org.slf4j.LoggerFactory | ||
| 18 | |||
| 19 | import javax.servlet.* | ||
| 20 | import javax.servlet.http.HttpServletRequest | ||
| 21 | import javax.servlet.http.HttpServletResponse | ||
| 22 | |||
| 23 | class McpFilter implements Filter { | ||
| 24 | protected final static Logger logger = LoggerFactory.getLogger(McpFilter.class) | ||
| 25 | |||
| 26 | private MoquiMcpServlet mcpServlet = new MoquiMcpServlet() | ||
| 27 | |||
| 28 | @Override | ||
| 29 | void init(FilterConfig filterConfig) throws ServletException { | ||
| 30 | logger.info("========== MCP FILTER INITIALIZED ==========") | ||
| 31 | // Initialize the servlet with filter config | ||
| 32 | mcpServlet.init(new ServletConfig() { | ||
| 33 | @Override | ||
| 34 | String getServletName() { return "McpFilter" } | ||
| 35 | @Override | ||
| 36 | ServletContext getServletContext() { return filterConfig.getServletContext() } | ||
| 37 | @Override | ||
| 38 | String getInitParameter(String name) { return filterConfig.getInitParameter(name) } | ||
| 39 | @Override | ||
| 40 | Enumeration<String> getInitParameterNames() { return filterConfig.getInitParameterNames() } | ||
| 41 | }) | ||
| 42 | } | ||
| 43 | |||
| 44 | @Override | ||
| 45 | void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) | ||
| 46 | throws IOException, ServletException { | ||
| 47 | |||
| 48 | logger.info("========== MCP FILTER DOFILTER CALLED ==========") | ||
| 49 | |||
| 50 | if (request instanceof HttpServletRequest && response instanceof HttpServletResponse) { | ||
| 51 | HttpServletRequest httpRequest = (HttpServletRequest) request | ||
| 52 | HttpServletResponse httpResponse = (HttpServletResponse) response | ||
| 53 | |||
| 54 | // Check if this is an MCP request | ||
| 55 | String path = httpRequest.getRequestURI() | ||
| 56 | logger.info("========== MCP FILTER PATH: {} ==========", path) | ||
| 57 | |||
| 58 | if (path != null && path.contains("/mcpservlet")) { | ||
| 59 | logger.info("========== MCP FILTER HANDLING REQUEST ==========") | ||
| 60 | try { | ||
| 61 | // Handle MCP request directly, don't continue chain | ||
| 62 | mcpServlet.service(httpRequest, httpResponse) | ||
| 63 | return | ||
| 64 | } catch (Exception e) { | ||
| 65 | logger.error("Error in MCP filter", e) | ||
| 66 | // Send error response directly | ||
| 67 | httpResponse.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR) | ||
| 68 | httpResponse.setContentType("application/json") | ||
| 69 | httpResponse.writer.write(groovy.json.JsonOutput.toJson([ | ||
| 70 | jsonrpc: "2.0", | ||
| 71 | error: [code: -32603, message: "Internal error: " + e.message], | ||
| 72 | id: null | ||
| 73 | ])) | ||
| 74 | return | ||
| 75 | } | ||
| 76 | } | ||
| 77 | } | ||
| 78 | |||
| 79 | // Not an MCP request, continue chain | ||
| 80 | chain.doFilter(request, response) | ||
| 81 | } | ||
| 82 | |||
| 83 | @Override | ||
| 84 | void destroy() { | ||
| 85 | mcpServlet.destroy() | ||
| 86 | logger.info("McpFilter destroyed") | ||
| 87 | } | ||
| 88 | } | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file |
This diff is collapsed.
Click to expand it.
This diff is collapsed.
Click to expand it.
src/main/webapp/WEB-INF/web.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, 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 | ||
| 9 | warranty. | ||
| 10 | |||
| 11 | You should have received a copy of the CC0 Public Domain Dedication | ||
| 12 | along with this software (see the LICENSE.md file). If not, see | ||
| 13 | <http://creativecommons.org/publicdomain/zero/1.0/>. | ||
| 14 | --> | ||
| 15 | |||
| 16 | <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" | ||
| 17 | xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
| 18 | xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee | ||
| 19 | http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" | ||
| 20 | version="4.0"> | ||
| 21 | |||
| 22 | <!-- Service-Based MCP Servlet Configuration --> | ||
| 23 | <servlet> | ||
| 24 | <servlet-name>ServiceBasedMcpServlet</servlet-name> | ||
| 25 | <servlet-class>org.moqui.mcp.ServiceBasedMcpServlet</servlet-class> | ||
| 26 | |||
| 27 | <!-- Configuration Parameters --> | ||
| 28 | <init-param> | ||
| 29 | <param-name>sseEndpoint</param-name> | ||
| 30 | <param-value>/sse</param-value> | ||
| 31 | </init-param> | ||
| 32 | <init-param> | ||
| 33 | <param-name>messageEndpoint</param-name> | ||
| 34 | <param-value>/mcp/message</param-value> | ||
| 35 | </init-param> | ||
| 36 | <init-param> | ||
| 37 | <param-name>keepAliveIntervalSeconds</param-name> | ||
| 38 | <param-value>30</param-value> | ||
| 39 | </init-param> | ||
| 40 | <init-param> | ||
| 41 | <param-name>maxConnections</param-name> | ||
| 42 | <param-value>100</param-value> | ||
| 43 | </init-param> | ||
| 44 | |||
| 45 | <!-- Enable async support for SSE --> | ||
| 46 | <async-supported>true</async-supported> | ||
| 47 | |||
| 48 | <!-- Load on startup --> | ||
| 49 | <load-on-startup>5</load-on-startup> | ||
| 50 | </servlet> | ||
| 51 | |||
| 52 | <!-- Servlet Mappings --> | ||
| 53 | <servlet-mapping> | ||
| 54 | <servlet-name>ServiceBasedMcpServlet</servlet-name> | ||
| 55 | <url-pattern>/sse/*</url-pattern> | ||
| 56 | </servlet-mapping> | ||
| 57 | |||
| 58 | <servlet-mapping> | ||
| 59 | <servlet-name>ServiceBasedMcpServlet</servlet-name> | ||
| 60 | <url-pattern>/mcp/message/*</url-pattern> | ||
| 61 | </servlet-mapping> | ||
| 62 | |||
| 63 | <servlet-mapping> | ||
| 64 | <servlet-name>ServiceBasedMcpServlet</servlet-name> | ||
| 65 | <url-pattern>/rpc/*</url-pattern> | ||
| 66 | </servlet-mapping> | ||
| 67 | |||
| 68 | <!-- Session Configuration --> | ||
| 69 | <session-config> | ||
| 70 | <session-timeout>30</session-timeout> | ||
| 71 | <cookie-config> | ||
| 72 | <http-only>true</http-only> | ||
| 73 | <secure>false</secure> | ||
| 74 | </cookie-config> | ||
| 75 | </session-config> | ||
| 76 | |||
| 77 | <!-- Security Constraints (optional - uncomment if needed) --> | ||
| 78 | <!-- | ||
| 79 | <security-constraint> | ||
| 80 | <web-resource-collection> | ||
| 81 | <web-resource-name>MCP Endpoints</web-resource-name> | ||
| 82 | <url-pattern>/sse/*</url-pattern> | ||
| 83 | <url-pattern>/mcp/message/*</url-pattern> | ||
| 84 | <url-pattern>/rpc/*</url-pattern> | ||
| 85 | </web-resource-collection> | ||
| 86 | <auth-constraint> | ||
| 87 | <role-name>admin</role-name> | ||
| 88 | </auth-constraint> | ||
| 89 | </security-constraint> | ||
| 90 | |||
| 91 | <login-config> | ||
| 92 | <auth-method>BASIC</auth-method> | ||
| 93 | <realm-name>Moqui MCP</realm-name> | ||
| 94 | </login-config> | ||
| 95 | --> | ||
| 96 | |||
| 97 | <!-- MIME Type Mappings --> | ||
| 98 | <mime-mapping> | ||
| 99 | <extension>json</extension> | ||
| 100 | <mime-type>application/json</mime-type> | ||
| 101 | </mime-mapping> | ||
| 102 | |||
| 103 | <!-- Default Welcome Files --> | ||
| 104 | <welcome-file-list> | ||
| 105 | <welcome-file>index.html</welcome-file> | ||
| 106 | <welcome-file>index.jsp</welcome-file> | ||
| 107 | </welcome-file-list> | ||
| 108 | |||
| 109 | </web-app> | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file |
web-sdk-services.xml
0 → 100644
| 1 | <?xml version="1.0" encoding="UTF-8"?> | ||
| 2 | <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" | ||
| 3 | xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
| 4 | xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee | ||
| 5 | http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" | ||
| 6 | version="4.0"> | ||
| 7 | |||
| 8 | <!-- MCP SDK Services Servlet Configuration --> | ||
| 9 | <servlet> | ||
| 10 | <servlet-name>McpSdkServicesServlet</servlet-name> | ||
| 11 | <servlet-class>org.moqui.mcp.McpSdkServicesServlet</servlet-class> | ||
| 12 | |||
| 13 | <!-- Configuration parameters --> | ||
| 14 | <init-param> | ||
| 15 | <param-name>moqui-name</param-name> | ||
| 16 | <param-value>moqui-mcp-2</param-value> | ||
| 17 | </init-param> | ||
| 18 | |||
| 19 | <!-- Enable async support (required for SSE) --> | ||
| 20 | <async-supported>true</async-supported> | ||
| 21 | |||
| 22 | <!-- Load on startup to initialize MCP server --> | ||
| 23 | <load-on-startup>1</load-on-startup> | ||
| 24 | </servlet> | ||
| 25 | |||
| 26 | <!-- Servlet mappings for MCP SDK Services endpoints --> | ||
| 27 | <!-- The MCP SDK will handle both SSE and message endpoints through this servlet --> | ||
| 28 | <servlet-mapping> | ||
| 29 | <servlet-name>McpSdkServicesServlet</servlet-name> | ||
| 30 | <url-pattern>/mcp/*</url-pattern> | ||
| 31 | </servlet-mapping> | ||
| 32 | |||
| 33 | <!-- Session configuration --> | ||
| 34 | <session-config> | ||
| 35 | <session-timeout>30</session-timeout> | ||
| 36 | <cookie-config> | ||
| 37 | <http-only>true</http-only> | ||
| 38 | <secure>false</secure> | ||
| 39 | </cookie-config> | ||
| 40 | </session-config> | ||
| 41 | |||
| 42 | </web-app> | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file |
web-sdk-sse.xml
0 → 100644
| 1 | <?xml version="1.0" encoding="UTF-8"?> | ||
| 2 | <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" | ||
| 3 | xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
| 4 | xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee | ||
| 5 | http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" | ||
| 6 | version="4.0"> | ||
| 7 | |||
| 8 | <!-- MCP SDK SSE Servlet Configuration --> | ||
| 9 | <servlet> | ||
| 10 | <servlet-name>McpSdkSseServlet</servlet-name> | ||
| 11 | <servlet-class>org.moqui.mcp.McpSdkSseServlet</servlet-class> | ||
| 12 | |||
| 13 | <!-- Configuration parameters --> | ||
| 14 | <init-param> | ||
| 15 | <param-name>moqui-name</param-name> | ||
| 16 | <param-value>moqui-mcp-2</param-value> | ||
| 17 | </init-param> | ||
| 18 | |||
| 19 | <!-- Enable async support (required for SSE) --> | ||
| 20 | <async-supported>true</async-supported> | ||
| 21 | |||
| 22 | <!-- Load on startup to initialize MCP server --> | ||
| 23 | <load-on-startup>1</load-on-startup> | ||
| 24 | </servlet> | ||
| 25 | |||
| 26 | <!-- Servlet mappings for MCP SDK SSE endpoints --> | ||
| 27 | <!-- The MCP SDK will handle both SSE and message endpoints through this servlet --> | ||
| 28 | <servlet-mapping> | ||
| 29 | <servlet-name>McpSdkSseServlet</servlet-name> | ||
| 30 | <url-pattern>/mcp/*</url-pattern> | ||
| 31 | </servlet-mapping> | ||
| 32 | |||
| 33 | <!-- Session configuration --> | ||
| 34 | <session-config> | ||
| 35 | <session-timeout>30</session-timeout> | ||
| 36 | <cookie-config> | ||
| 37 | <http-only>true</http-only> | ||
| 38 | <secure>false</secure> | ||
| 39 | </cookie-config> | ||
| 40 | </session-config> | ||
| 41 | |||
| 42 | </web-app> | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file |
web-sse.xml
0 → 100644
| 1 | <?xml version="1.0" encoding="UTF-8"?> | ||
| 2 | <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" | ||
| 3 | xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
| 4 | xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee | ||
| 5 | http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" | ||
| 6 | version="4.0"> | ||
| 7 | |||
| 8 | <!-- MCP SSE Servlet Configuration --> | ||
| 9 | <servlet> | ||
| 10 | <servlet-name>McpSseServlet</servlet-name> | ||
| 11 | <servlet-class>org.moqui.mcp.McpSseServlet</servlet-class> | ||
| 12 | |||
| 13 | <!-- Configuration parameters --> | ||
| 14 | <init-param> | ||
| 15 | <param-name>moqui-name</param-name> | ||
| 16 | <param-value>moqui-mcp-2</param-value> | ||
| 17 | </init-param> | ||
| 18 | |||
| 19 | <init-param> | ||
| 20 | <param-name>sseEndpoint</param-name> | ||
| 21 | <param-value>/sse</param-value> | ||
| 22 | </init-param> | ||
| 23 | |||
| 24 | <init-param> | ||
| 25 | <param-name>messageEndpoint</param-name> | ||
| 26 | <param-value>/mcp/message</param-value> | ||
| 27 | </init-param> | ||
| 28 | |||
| 29 | <init-param> | ||
| 30 | <param-name>keepAliveIntervalSeconds</param-name> | ||
| 31 | <param-value>30</param-value> | ||
| 32 | </init-param> | ||
| 33 | |||
| 34 | <init-param> | ||
| 35 | <param-name>maxConnections</param-name> | ||
| 36 | <param-value>100</param-value> | ||
| 37 | </init-param> | ||
| 38 | |||
| 39 | <!-- Enable async support --> | ||
| 40 | <async-supported>true</async-supported> | ||
| 41 | </servlet> | ||
| 42 | |||
| 43 | <!-- Servlet mappings for MCP SSE endpoints --> | ||
| 44 | <servlet-mapping> | ||
| 45 | <servlet-name>McpSseServlet</servlet-name> | ||
| 46 | <url-pattern>/sse/*</url-pattern> | ||
| 47 | </servlet-mapping> | ||
| 48 | |||
| 49 | <servlet-mapping> | ||
| 50 | <servlet-name>McpSseServlet</servlet-name> | ||
| 51 | <url-pattern>/mcp/message/*</url-pattern> | ||
| 52 | </servlet-mapping> | ||
| 53 | |||
| 54 | <!-- Session configuration --> | ||
| 55 | <session-config> | ||
| 56 | <session-timeout>30</session-timeout> | ||
| 57 | <cookie-config> | ||
| 58 | <http-only>true</http-only> | ||
| 59 | <secure>false</secure> | ||
| 60 | </cookie-config> | ||
| 61 | </session-config> | ||
| 62 | |||
| 63 | </web-app> | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file |
-
Please register or sign in to post a comment