This is an automated email from the ASF dual-hosted git repository. robertlazarski pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/axis-axis2-java-core.git
commit ef24536772c405b18cd25c0fd16446c030c2dd18 Author: Robert Lazarski <[email protected]> AuthorDate: Sat Apr 11 05:34:30 2026 -1000 Clean up MCP/OpenAPI docs for 2.0.1 release; fix XML parse bug - Fix unescaped '<' in BigDataH2Service services.xml mcpInputSchema ("<10MB" broke XML parsing on all containers) - Replace generic placeholder service example with FinancialBenchmarkService in json-rpc-mcp-guide.xml - Update inputSchema status from "not implemented" to "implemented" (mcpInputSchema in services.xml has been working since April) - Convert all curl examples to HTTPS/HTTP2 on port 8443 (Tomcat mTLS, WildFly self-signed cert, both ALPN h2 verified) - Add container/JDK testing matrix (WildFly 32/39, Tomcat 11, OpenJDK 21/25 — all validated) - Inline full test flow in WildFly README (was cross-ref to Tomcat) - Add quick-start build/deploy/test instructions to mcp-examples.md - Reference sample READMEs from main docs (mcp-architecture.md, json-rpc-mcp-guide.xml) for discoverability - Remove stale Axis2/C next-steps (C1 complete, code committed) Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]> --- .../userguide/springbootdemo-tomcat11/README.md | 33 +++-- .../bigdata_h2_resources/services.xml | 2 +- .../src/userguide/springbootdemo-wildfly/README.md | 78 +++++++++++- src/site/markdown/docs/mcp-architecture.md | 25 ++-- src/site/markdown/docs/mcp-examples.md | 137 ++++++++++++++++++--- src/site/xdoc/docs/json-rpc-mcp-guide.xml | 41 ++++-- 6 files changed, 258 insertions(+), 58 deletions(-) diff --git a/modules/samples/userguide/src/userguide/springbootdemo-tomcat11/README.md b/modules/samples/userguide/src/userguide/springbootdemo-tomcat11/README.md index 10e000b035..3aa9b68bd0 100644 --- a/modules/samples/userguide/src/userguide/springbootdemo-tomcat11/README.md +++ b/modules/samples/userguide/src/userguide/springbootdemo-tomcat11/README.md @@ -81,19 +81,30 @@ reason. Do not rename the directory before copying to `webapps/`. ## Test flow -### 1. Verify OpenAPI docs +All tests use **HTTPS/HTTP2 on port 8443** with mTLS client certificates. The Tomcat connector +requires `certificateVerification="required"` — plain HTTP is not available. + +Set up the cert variables first: + +```bash +CERTS=/path/to/axis-axis2-java-core/certs +CURL_MTLS="curl -s --http2 --cert $CERTS/client.crt --key $CERTS/client.key --cacert $CERTS/ca.crt" +``` + +### 1. Verify OpenAPI and MCP endpoints ```bash -curl http://localhost:8080/axis2-json-api/openapi.json -curl http://localhost:8080/axis2-json-api/openapi.yaml +$CURL_MTLS https://localhost:8443/axis2-json-api/openapi.json +$CURL_MTLS https://localhost:8443/axis2-json-api/openapi.yaml +$CURL_MTLS https://localhost:8443/axis2-json-api/openapi-mcp.json # Interactive UI: -curl http://localhost:8080/axis2-json-api/swagger-ui +$CURL_MTLS https://localhost:8443/axis2-json-api/swagger-ui ``` ### 2. Login (get Bearer token) ```bash -curl -s -X POST http://localhost:8080/axis2-json-api/services/loginService \ +$CURL_MTLS -X POST https://localhost:8443/axis2-json-api/services/loginService \ -H 'Content-Type: application/json' \ -d '{"doLogin":[{"arg0":{"email":"[email protected]","credentials":"userguide"}}]}' ``` @@ -107,7 +118,7 @@ characters). ```bash TOKEN="<token from step 2>" -curl -s -X POST http://localhost:8080/axis2-json-api/services/testws \ +$CURL_MTLS -X POST https://localhost:8443/axis2-json-api/services/testws \ -H 'Content-Type: application/json' \ -H "Authorization: Bearer $TOKEN" \ -d '{"doTestws":[{"arg0":{"messagein":"hello world"}}]}' @@ -115,11 +126,11 @@ curl -s -X POST http://localhost:8080/axis2-json-api/services/testws \ ### 4. Call BigData service -`datasetSize` is in bytes. Size determines processing path: <10 MB → standard, +`datasetSize` is in bytes. Size determines processing path: under 10 MB → standard, 10–50 MB → multiplexing, >50 MB → streaming. Use at least 1 000 000 to get populated results. ```bash -curl -s -X POST http://localhost:8080/axis2-json-api/services/BigDataH2Service \ +$CURL_MTLS -X POST https://localhost:8443/axis2-json-api/services/BigDataH2Service \ -H 'Content-Type: application/json' \ -H "Authorization: Bearer $TOKEN" \ -d '{"processBigDataSet":[{"arg0":{"datasetId":"test-001","datasetSize":1000000,"processingMode":"streaming","enableMemoryOptimization":true,"analyticsType":"summary"}}]}' @@ -132,19 +143,19 @@ Response includes `processedRecordCount`, `http2Optimized`, `memoryOptimized`, a ```bash # Portfolio variance — O(n²) covariance matrix -curl -s -X POST http://localhost:8080/axis2-json-api/services/FinancialBenchmarkService \ +$CURL_MTLS -X POST https://localhost:8443/axis2-json-api/services/FinancialBenchmarkService \ -H 'Content-Type: application/json' \ -H "Authorization: Bearer $TOKEN" \ -d '{"portfolioVariance":[{"arg0":{"nAssets":2,"weights":[0.6,0.4],"covarianceMatrix":[[0.04,0.006],[0.006,0.09]],"normalizeWeights":false,"nPeriodsPerYear":252}}]}' # Monte Carlo VaR — GBM simulation -curl -s -X POST http://localhost:8080/axis2-json-api/services/FinancialBenchmarkService \ +$CURL_MTLS -X POST https://localhost:8443/axis2-json-api/services/FinancialBenchmarkService \ -H 'Content-Type: application/json' \ -H "Authorization: Bearer $TOKEN" \ -d '{"monteCarlo":[{"arg0":{"nSimulations":10000,"nPeriods":252,"initialValue":100.0,"expectedReturn":0.08,"volatility":0.20,"nPeriodsPerYear":252,"randomSeed":42}}]}' # Scenario analysis — probability-weighted expected return -curl -s -X POST http://localhost:8080/axis2-json-api/services/FinancialBenchmarkService \ +$CURL_MTLS -X POST https://localhost:8443/axis2-json-api/services/FinancialBenchmarkService \ -H 'Content-Type: application/json' \ -H "Authorization: Bearer $TOKEN" \ -d '{"scenarioAnalysis":[{"arg0":{"assets":[{"assetId":1,"currentPrice":100.0,"positionSize":100,"scenarios":[{"price":120.0,"probability":0.3},{"price":100.0,"probability":0.5},{"price":75.0,"probability":0.2}]}],"useHashLookup":true,"probTolerance":0.001}}]}' diff --git a/modules/samples/userguide/src/userguide/springbootdemo-tomcat11/resources-axis2/bigdata_h2_resources/services.xml b/modules/samples/userguide/src/userguide/springbootdemo-tomcat11/resources-axis2/bigdata_h2_resources/services.xml index 64508f0753..150e208892 100644 --- a/modules/samples/userguide/src/userguide/springbootdemo-tomcat11/resources-axis2/bigdata_h2_resources/services.xml +++ b/modules/samples/userguide/src/userguide/springbootdemo-tomcat11/resources-axis2/bigdata_h2_resources/services.xml @@ -81,7 +81,7 @@ "required": ["datasetId", "datasetSize"], "properties": { "datasetId": {"type": "string", "description": "Unique dataset identifier for tracking"}, - "datasetSize": {"type": "integer", "description": "Dataset size in bytes (determines processing mode: streaming for 50MB+, multiplexing for 10-50MB, standard for <10MB)"} + "datasetSize": {"type": "integer", "description": "Dataset size in bytes (determines processing mode: streaming for 50MB+, multiplexing for 10-50MB, standard for under 10MB)"} } }</parameter> diff --git a/modules/samples/userguide/src/userguide/springbootdemo-wildfly/README.md b/modules/samples/userguide/src/userguide/springbootdemo-wildfly/README.md index c9b4870287..be358e434a 100644 --- a/modules/samples/userguide/src/userguide/springbootdemo-wildfly/README.md +++ b/modules/samples/userguide/src/userguide/springbootdemo-wildfly/README.md @@ -22,7 +22,7 @@ Axis2 JSON-RPC services deployed as a WAR in **WildFly** (Undertow), using Spring Boot 3.x as a configuration framework only — there is no embedded container. -Tested with: **WildFly 39.0.1.Final** · **OpenJDK 25** · **Spring Boot 3.4.3** +Tested with: **WildFly 32.0.1.Final** (OpenJDK 21) · **WildFly 39.0.1.Final** (OpenJDK 25) · **Spring Boot 3.4.3** All Java source is shared from `../springbootdemo-tomcat11/src/main/java` via `build-helper-maven-plugin`. This module only adds WildFly-specific WEB-INF descriptors. @@ -146,7 +146,77 @@ retried by a new WildFly instance — it must be removed. ## Test flow -See `../springbootdemo-tomcat11/README.md` for the full curl-based test sequence; it applies -identically to WildFly (same context path, same JSON-RPC format, same credentials). +All tests use **HTTPS/HTTP2 on port 8443**. WildFly uses a self-signed certificate +(`generate-self-signed-certificate-host="localhost"`), so `-k` is needed to skip +certificate verification. -The only difference: use port `8080` on WildFly (same default as Tomcat 11). +```bash +CURL_H2="curl -s --http2 -k" +``` + +### 1. Verify OpenAPI and MCP endpoints + +```bash +$CURL_H2 https://localhost:8443/axis2-json-api/openapi.json +$CURL_H2 https://localhost:8443/axis2-json-api/openapi.yaml +$CURL_H2 https://localhost:8443/axis2-json-api/openapi-mcp.json +# Interactive UI: +$CURL_H2 https://localhost:8443/axis2-json-api/swagger-ui +``` + +### 2. Login (get Bearer token) + +```bash +$CURL_H2 -X POST https://localhost:8443/axis2-json-api/services/loginService \ + -H 'Content-Type: application/json' \ + -d '{"doLogin":[{"arg0":{"email":"[email protected]","credentials":"userguide"}}]}' +``` + +Response: `{"response":{"token":"<TOKEN>","uuid":"<UUID>","status":"OK"}}` + +### 3. Call protected service (testws) + +`messagein` must pass ESAPI `SafeString` validation (`[A-Za-z0-9.,\-_ ]*` — no `+` or special +characters). + +```bash +TOKEN="<token from step 2>" +$CURL_H2 -X POST https://localhost:8443/axis2-json-api/services/testws \ + -H 'Content-Type: application/json' \ + -H "Authorization: Bearer $TOKEN" \ + -d '{"doTestws":[{"arg0":{"messagein":"hello world"}}]}' +``` + +### 4. Call BigData service + +`datasetSize` is in bytes. Size determines processing path: under 10 MB → standard, +10–50 MB → multiplexing, >50 MB → streaming. Use at least 1 000 000 to get populated results. + +```bash +$CURL_H2 -X POST https://localhost:8443/axis2-json-api/services/BigDataH2Service \ + -H 'Content-Type: application/json' \ + -H "Authorization: Bearer $TOKEN" \ + -d '{"processBigDataSet":[{"arg0":{"datasetId":"test-001","datasetSize":1000000,"processingMode":"streaming","enableMemoryOptimization":true,"analyticsType":"summary"}}]}' +``` + +### 5. Financial Benchmark Service + +```bash +# Portfolio variance — O(n²) covariance matrix +$CURL_H2 -X POST https://localhost:8443/axis2-json-api/services/FinancialBenchmarkService \ + -H 'Content-Type: application/json' \ + -H "Authorization: Bearer $TOKEN" \ + -d '{"portfolioVariance":[{"arg0":{"nAssets":2,"weights":[0.6,0.4],"covarianceMatrix":[[0.04,0.006],[0.006,0.09]],"normalizeWeights":false,"nPeriodsPerYear":252}}]}' + +# Monte Carlo VaR — GBM simulation +$CURL_H2 -X POST https://localhost:8443/axis2-json-api/services/FinancialBenchmarkService \ + -H 'Content-Type: application/json' \ + -H "Authorization: Bearer $TOKEN" \ + -d '{"monteCarlo":[{"arg0":{"nSimulations":10000,"nPeriods":252,"initialValue":100.0,"expectedReturn":0.08,"volatility":0.20,"nPeriodsPerYear":252,"randomSeed":42}}]}' + +# Scenario analysis — probability-weighted expected return +$CURL_H2 -X POST https://localhost:8443/axis2-json-api/services/FinancialBenchmarkService \ + -H 'Content-Type: application/json' \ + -H "Authorization: Bearer $TOKEN" \ + -d '{"scenarioAnalysis":[{"arg0":{"assets":[{"assetId":1,"currentPrice":100.0,"positionSize":100,"scenarios":[{"price":120.0,"probability":0.3},{"price":100.0,"probability":0.5},{"price":75.0,"probability":0.2}]}],"useHashLookup":true,"probTolerance":0.001}}]}' +``` diff --git a/src/site/markdown/docs/mcp-architecture.md b/src/site/markdown/docs/mcp-architecture.md index e2089ee446..d6ef60edd0 100644 --- a/src/site/markdown/docs/mcp-architecture.md +++ b/src/site/markdown/docs/mcp-architecture.md @@ -32,12 +32,16 @@ modelcontextprotocol.io. ### Reference implementations +Build, deploy, and test instructions for each container are in the sample READMEs: +- **Tomcat 11**: `modules/samples/userguide/src/userguide/springbootdemo-tomcat11/README.md` +- **WildFly 32/39**: `modules/samples/userguide/src/userguide/springbootdemo-wildfly/README.md` + ``` springbootdemo-tomcat11 base URL: https://localhost:8443/axis2-json-api - LoginService (auth, port 8080 only) - BigDataH2Service (streaming/multiplexing demo, accessible via mTLS on 8443) -springbootdemo-wildfly base URL: http://localhost:8080/axis2-json-api +springbootdemo-wildfly base URL: https://localhost:8443/axis2-json-api - LoginService (JWT auth) - FinancialBenchmarkService (portfolioVariance, monteCarlo VaR, scenarioAnalysis) - BigDataH2Service (HTTP/2 streaming) @@ -330,12 +334,6 @@ opt-in per-operation. ## Next Steps -### C1 — complete ✅ - -`finbench_mcp.c` + `finbench_mcp_main.c` committed to `axis-axis2-c-core`. -Builds with `build_financial_service.sh`; installs to `/usr/local/axis2c/bin/financial-benchmark-mcp`. -See `docs/MCP.md` in the `axis-axis2-c-core` repo for the full C implementation plan. - ### Track A remaining | Step | Work | Notes | @@ -349,11 +347,16 @@ See `docs/MCP.md` in the `axis-axis2-c-core` repo for the full C implementation 2. stdio transport first (B1) — validates JSON-RPC 2.0 ↔ MessageContext translation 3. HTTP/SSE transport (B2) — reuses Axis2 HTTP infrastructure -### Axis2/C deployment +### Testing matrix + +MCP and OpenAPI support needs validation across the full container/JDK matrix: -`build_financial_service.sh` in `axis-axis2-c-core` needs to be run on the target -host after Axis2/C is installed. The service is committed and compiles clean — the -script is the only remaining deployment step. +| Container | JDK | MCP | OpenAPI | Status | +|-----------|-----|-----|---------|--------| +| WildFly 32 | OpenJDK 21 | ✅ | ✅ | Validated | +| WildFly 39 | OpenJDK 25 | ✅ | ✅ | Validated | +| Tomcat 11 | OpenJDK 21 | ✅ | ✅ | Validated | +| Tomcat 11 | OpenJDK 25 | ✅ | ✅ | Validated | --- diff --git a/src/site/markdown/docs/mcp-examples.md b/src/site/markdown/docs/mcp-examples.md index 9142662b65..1b3bef0fef 100644 --- a/src/site/markdown/docs/mcp-examples.md +++ b/src/site/markdown/docs/mcp-examples.md @@ -27,11 +27,15 @@ framing) is excluded. The computation comparison is apples-to-apples. ## Authentication +All examples use **HTTPS/HTTP2 on port 8443**. WildFly uses a self-signed certificate, +so `-k` skips certificate verification. Tomcat uses mTLS with CA-signed client certs +(see `mcp-architecture.md` for PKI details). + Axis2/Java requires JWT authentication via Spring Security. All financial service calls need a `Bearer` token obtained from the login endpoint: ```bash -TOKEN=$(curl -s http://localhost:8080/axis2-json-api/services/loginService \ +TOKEN=$(curl -s --http2 -k https://localhost:8443/axis2-json-api/services/loginService \ -H 'Content-Type: application/json' \ -d '{"doLogin":[{"arg0":{"email":"[email protected]","credentials":"userguide"}}]}' \ | python3 -c "import sys,json; print(json.load(sys.stdin)['response']['token'])") @@ -71,7 +75,7 @@ client sees only standard MCP JSON-RPC. "axis2-java-finbench": { "command": "java", "args": ["-jar", "/path/to/axis2-mcp-bridge-2.0.1-SNAPSHOT-exe.jar", - "--base-url", "http://localhost:8080/axis2-json-api"] + "--base-url", "https://localhost:8443/axis2-json-api"] } } } @@ -82,7 +86,7 @@ client sees only standard MCP JSON-RPC. echo '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{ "name":"portfolioVariance","arguments":{...}}}' \ | java -jar axis2-mcp-bridge-2.0.1-SNAPSHOT-exe.jar \ - --base-url http://localhost:8080/axis2-json-api + --base-url https://localhost:8443/axis2-json-api ``` All curl examples below include paired MCP stdio equivalents. @@ -94,7 +98,7 @@ All curl examples below include paired MCP stdio equivalents. ### Portfolio Variance — 5 assets ```bash -curl -s http://localhost:8080/axis2-json-api/services/FinancialBenchmarkService \ +curl -s --http2 -k https://localhost:8443/axis2-json-api/services/FinancialBenchmarkService \ -H 'Content-Type: application/json' -H "Authorization: Bearer $TOKEN" \ -d '{"portfolioVariance":[{"arg0":{ "nAssets": 5, @@ -128,7 +132,7 @@ curl -s http://localhost:8080/axis2-json-api/services/FinancialBenchmarkService **MCP stdio equivalent:** ```bash echo '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"portfolioVariance","arguments":{"nAssets":5,"weights":[0.25,0.25,0.20,0.15,0.15],"covarianceMatrix":[[0.0691,0.0313,0.0457,0.0272,-0.0035],[0.0313,0.0976,0.0591,0.0408,0.0058],[0.0457,0.0591,0.1207,0.0437,-0.0086],[0.0272,0.0408,0.0437,0.0638,0.0015],[-0.0035,0.0058,-0.0086,0.0015,0.0303]],"normalizeWeights":true}}}' \ - | java -jar axis2-mcp-bridge-2.0.1-SNAPSHOT-exe.jar --base-url http://localhost:8080/axis2-json-api + | java -jar axis2-mcp-bridge-2.0.1-SNAPSHOT-exe.jar --base-url https://localhost:8443/axis2-json-api ``` ### Portfolio Variance — 500 assets @@ -147,7 +151,7 @@ for i in range(n): print(json.dumps({'portfolioVariance':[{'arg0':{'nAssets':n,'weights':w,'covarianceMatrix':c}}]}))" \ > /tmp/pv500.json -curl -s http://localhost:8080/axis2-json-api/services/FinancialBenchmarkService \ +curl -s --http2 -k https://localhost:8443/axis2-json-api/services/FinancialBenchmarkService \ -H 'Content-Type: application/json' -H "Authorization: Bearer $TOKEN" \ -d @/tmp/pv500.json ``` @@ -178,7 +182,7 @@ Z ~ N(0,1). Run 100,000 paths, sort the terminal values, read off the this nightly for regulatory capital calculations. ```bash -curl -s http://localhost:8080/axis2-json-api/services/FinancialBenchmarkService \ +curl -s --http2 -k https://localhost:8443/axis2-json-api/services/FinancialBenchmarkService \ -H 'Content-Type: application/json' -H "Authorization: Bearer $TOKEN" \ -d '{"monteCarlo":[{"arg0":{ "nSimulations": 100000, @@ -210,7 +214,7 @@ curl -s http://localhost:8080/axis2-json-api/services/FinancialBenchmarkService **MCP stdio equivalent:** ```bash echo '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"monteCarlo","arguments":{"nSimulations":100000,"nPeriods":252,"initialValue":1000000,"expectedReturn":0.10,"volatility":0.198,"nPeriodsPerYear":252}}}' \ - | java -jar axis2-mcp-bridge-2.0.1-SNAPSHOT-exe.jar --base-url http://localhost:8080/axis2-json-api + | java -jar axis2-mcp-bridge-2.0.1-SNAPSHOT-exe.jar --base-url https://localhost:8443/axis2-json-api ``` --- @@ -228,7 +232,7 @@ payload. The bridge handles the Axis2 JSON-RPC wrapping transparently. **Step 1 — Baseline:** ```bash -curl -s http://localhost:8080/axis2-json-api/services/FinancialBenchmarkService \ +curl -s --http2 -k https://localhost:8443/axis2-json-api/services/FinancialBenchmarkService \ -H 'Content-Type: application/json' -H "Authorization: Bearer $TOKEN" \ -d '{"portfolioVariance":[{"arg0":{ "nAssets": 5, @@ -259,7 +263,7 @@ curl -s http://localhost:8080/axis2-json-api/services/FinancialBenchmarkService **Step 2 — Stressed (all pairwise correlations → 0.8):** ```bash -curl -s http://localhost:8080/axis2-json-api/services/FinancialBenchmarkService \ +curl -s --http2 -k https://localhost:8443/axis2-json-api/services/FinancialBenchmarkService \ -H 'Content-Type: application/json' -H "Authorization: Bearer $TOKEN" \ -d '{"portfolioVariance":[{"arg0":{ "nAssets": 5, @@ -290,7 +294,7 @@ curl -s http://localhost:8080/axis2-json-api/services/FinancialBenchmarkService **Step 3 — Monte Carlo on stressed portfolio (100K paths):** ```bash -curl -s http://localhost:8080/axis2-json-api/services/FinancialBenchmarkService \ +curl -s --http2 -k https://localhost:8443/axis2-json-api/services/FinancialBenchmarkService \ -H 'Content-Type: application/json' -H "Authorization: Bearer $TOKEN" \ -d '{"monteCarlo":[{"arg0":{ "nSimulations": 100000, @@ -321,7 +325,7 @@ curl -s http://localhost:8080/axis2-json-api/services/FinancialBenchmarkService **MCP stdio equivalent (stressed MC):** ```bash echo '{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"monteCarlo","arguments":{"nSimulations":100000,"nPeriods":252,"initialValue":1000000,"expectedReturn":0.10,"volatility":0.255,"nPeriodsPerYear":252}}}' \ - | java -jar axis2-mcp-bridge-2.0.1-SNAPSHOT-exe.jar --base-url http://localhost:8080/axis2-json-api + | java -jar axis2-mcp-bridge-2.0.1-SNAPSHOT-exe.jar --base-url https://localhost:8443/axis2-json-api ``` **Comparison — Axis2/C vs Axis2/Java (same inputs, same day):** @@ -355,7 +359,7 @@ as Live Examples). **Candidate A — European semi (vol 44%, ρ = 0.68 to tech):** ```bash -curl -s http://localhost:8080/axis2-json-api/services/FinancialBenchmarkService \ +curl -s --http2 -k https://localhost:8443/axis2-json-api/services/FinancialBenchmarkService \ -H 'Content-Type: application/json' -H "Authorization: Bearer $TOKEN" \ -d '{"portfolioVariance":[{"arg0":{ "nAssets": 6, @@ -379,7 +383,7 @@ curl -s http://localhost:8080/axis2-json-api/services/FinancialBenchmarkService **Candidate B — Japanese peer (vol 38%, ρ = 0.31 to US tech):** ```bash -curl -s http://localhost:8080/axis2-json-api/services/FinancialBenchmarkService \ +curl -s --http2 -k https://localhost:8443/axis2-json-api/services/FinancialBenchmarkService \ -H 'Content-Type: application/json' -H "Authorization: Bearer $TOKEN" \ -d '{"portfolioVariance":[{"arg0":{ "nAssets": 6, @@ -404,14 +408,14 @@ curl -s http://localhost:8080/axis2-json-api/services/FinancialBenchmarkService ```bash # European candidate (vol 21.1%) -curl -s http://localhost:8080/axis2-json-api/services/FinancialBenchmarkService \ +curl -s --http2 -k https://localhost:8443/axis2-json-api/services/FinancialBenchmarkService \ -H 'Content-Type: application/json' -H "Authorization: Bearer $TOKEN" \ -d '{"monteCarlo":[{"arg0":{"nSimulations":100000,"nPeriods":252, "initialValue":1000000,"expectedReturn":0.10,"volatility":0.211, "nPeriodsPerYear":252}}]}' # Japanese candidate (vol 20.1%) -curl -s http://localhost:8080/axis2-json-api/services/FinancialBenchmarkService \ +curl -s --http2 -k https://localhost:8443/axis2-json-api/services/FinancialBenchmarkService \ -H 'Content-Type: application/json' -H "Authorization: Bearer $TOKEN" \ -d '{"monteCarlo":[{"arg0":{"nSimulations":100000,"nPeriods":252, "initialValue":1000000,"expectedReturn":0.10,"volatility":0.201, @@ -459,7 +463,7 @@ Run `monteCarlo` at 1K, 10K, 100K, and 1M paths: ```bash for N in 1000 10000 100000 1000000; do - curl -s http://localhost:8080/axis2-json-api/services/FinancialBenchmarkService \ + curl -s --http2 -k https://localhost:8443/axis2-json-api/services/FinancialBenchmarkService \ -H 'Content-Type: application/json' -H "Authorization: Bearer $TOKEN" \ -d "{\"monteCarlo\":[{\"arg0\":{\"nSimulations\":$N,\"nPeriods\":252, \"initialValue\":1000000,\"expectedReturn\":0.10,\"volatility\":0.198, @@ -470,7 +474,7 @@ done **MCP stdio equivalent (example for 100K):** ```bash echo '{"jsonrpc":"2.0","id":4,"method":"tools/call","params":{"name":"monteCarlo","arguments":{"nSimulations":100000,"nPeriods":252,"initialValue":1000000,"expectedReturn":0.10,"volatility":0.198,"nPeriodsPerYear":252}}}' \ - | java -jar axis2-mcp-bridge-2.0.1-SNAPSHOT-exe.jar --base-url http://localhost:8080/axis2-json-api + | java -jar axis2-mcp-bridge-2.0.1-SNAPSHOT-exe.jar --base-url https://localhost:8443/axis2-json-api ``` **Axis2/Java results (2026-04-08):** @@ -575,7 +579,7 @@ produce the same answers. The choice is deployment context, not functionality. Axis2/Java exposes an MCP tool catalog at: ``` -GET http://localhost:8080/axis2-json-api/openapi-mcp.json +GET https://localhost:8443/axis2-json-api/openapi-mcp.json ``` This endpoint returns the same tool schema structure that Claude Desktop @@ -586,6 +590,101 @@ Axis2/C MCP stdio server. --- +## Container/JDK Testing Matrix + +MCP bridge and OpenAPI endpoints need validation across all supported containers +and JDK versions before the 2.0.1 release: + +| Container | JDK | MCP Bridge | OpenAPI/Swagger UI | Status | +|-----------|-----|------------|-------------------|--------| +| WildFly 32 | OpenJDK 21 | ✅ Tested | ✅ Tested | Validated | +| WildFly 39 | OpenJDK 25 | ✅ Tested | ✅ Tested | Validated | +| Tomcat 11 | OpenJDK 21 | ✅ Tested | ✅ Tested | Validated | +| Tomcat 11 | OpenJDK 25 | ✅ Tested | ✅ Tested | Validated | + +All four container/JDK combinations negotiate HTTP/2 via ALPN over TLS. + +--- + +## Build and Deploy + +### WildFly + +Full build, deploy, and test instructions are in +`modules/samples/userguide/src/userguide/springbootdemo-wildfly/README.md`. +Quick start: + +```bash +cd modules/samples/userguide/src/userguide/springbootdemo-wildfly +mvn -Dmaven.test.skip.exec clean install + +# Deploy exploded WAR to WildFly +rsync -a --delete target/deploy/axis2-json-api/ ~/wildfly/standalone/deployments/axis2-json-api.war/ +touch ~/wildfly/standalone/deployments/axis2-json-api.war.dodeploy +``` + +### Tomcat 11 + +Full build, deploy, and test instructions are in +`modules/samples/userguide/src/userguide/springbootdemo-tomcat11/README.md`. +Quick start: + +```bash +cd modules/samples/userguide/src/userguide/springbootdemo-tomcat11 +mvn -Dmaven.test.skip.exec clean install + +# Deploy exploded WAR to Tomcat +cp -r target/deploy/axis2-json-api /path/to/tomcat/webapps/ +``` + +### Verify all endpoints after deploy + +**Tomcat 11** (HTTPS/HTTP2 on port 8443 with mTLS): + +```bash +CERTS=/path/to/axis-axis2-java-core/certs +CURL_MTLS="curl -s --http2 --cert $CERTS/client.crt --key $CERTS/client.key --cacert $CERTS/ca.crt" + +# OpenAPI and MCP (no auth required, but mTLS handshake still needed) +$CURL_MTLS https://localhost:8443/axis2-json-api/openapi.json +$CURL_MTLS https://localhost:8443/axis2-json-api/openapi.yaml +$CURL_MTLS https://localhost:8443/axis2-json-api/openapi-mcp.json +$CURL_MTLS https://localhost:8443/axis2-json-api/swagger-ui + +# Login +TOKEN=$($CURL_MTLS -X POST https://localhost:8443/axis2-json-api/services/loginService \ + -H 'Content-Type: application/json' \ + -d '{"doLogin":[{"arg0":{"email":"[email protected]","credentials":"userguide"}}]}' \ + | python3 -c "import sys,json; print(json.load(sys.stdin)['response']['token'])") + +# Financial benchmark +$CURL_MTLS -X POST https://localhost:8443/axis2-json-api/services/FinancialBenchmarkService \ + -H 'Content-Type: application/json' -H "Authorization: Bearer $TOKEN" \ + -d '{"portfolioVariance":[{"arg0":{"nAssets":2,"weights":[0.6,0.4],"covarianceMatrix":[[0.04,0.006],[0.006,0.09]]}}]}' +``` + +**WildFly 32/39** (HTTPS/HTTP2 on port 8443 with self-signed cert, JWT auth): + +```bash +# OpenAPI and MCP +curl -s --http2 -k https://localhost:8443/axis2-json-api/openapi.json +curl -s --http2 -k https://localhost:8443/axis2-json-api/openapi-mcp.json + +# Login + financial benchmark +TOKEN=$(curl -s --http2 -k https://localhost:8443/axis2-json-api/services/loginService \ + -H 'Content-Type: application/json' \ + -d '{"doLogin":[{"arg0":{"email":"[email protected]","credentials":"userguide"}}]}' \ + | python3 -c "import sys,json; print(json.load(sys.stdin)['response']['token'])") + +curl -s --http2 -k https://localhost:8443/axis2-json-api/services/FinancialBenchmarkService \ + -H 'Content-Type: application/json' -H "Authorization: Bearer $TOKEN" \ + -d '{"portfolioVariance":[{"arg0":{"nAssets":2,"weights":[0.6,0.4],"covarianceMatrix":[[0.04,0.006],[0.006,0.09]]}}]}' +``` + +See the sample READMEs for the complete test flow covering all services. + +--- + ## WildFly 32 Deployment Notes See `WILDFLY32_DEPLOY_STATE.md` in the Axis2/C repo for the full deployment diff --git a/src/site/xdoc/docs/json-rpc-mcp-guide.xml b/src/site/xdoc/docs/json-rpc-mcp-guide.xml index b768449eb6..9b2d46688a 100644 --- a/src/site/xdoc/docs/json-rpc-mcp-guide.xml +++ b/src/site/xdoc/docs/json-rpc-mcp-guide.xml @@ -33,6 +33,12 @@ that target Axis2 JSON-RPC services and need to understand the auto-generated MCP tool catalog, the required envelope format, authentication flow, and current limitations.</p> +<p><strong>Quick start:</strong> For step-by-step build, deploy, and test instructions +(including curl commands for every endpoint), see the sample READMEs: +<code>modules/samples/userguide/src/userguide/springbootdemo-tomcat11/README.md</code> (Tomcat 11) +and <code>modules/samples/userguide/src/userguide/springbootdemo-wildfly/README.md</code> +(WildFly 32/39).</p> + <p><strong>In one sentence:</strong> Axis2 auto-generates an MCP tool catalog from its deployed services, accessible at <code>/openapi-mcp.json</code>, that tells MCP clients the exact JSON-RPC envelope format, auth requirements, and endpoint URL for every @@ -138,16 +144,26 @@ before calling any tool:</p> } }, { - "name": "getCalculations", - "description": "CalculationService: getCalculations", - "inputSchema": { "type": "object", "properties": {}, "required": [] }, - "endpoint": "POST /services/CalculationService/getCalculations", - "x-axis2-payloadTemplate": "{\"getCalculations\":[{\"arg0\":{}}]}", + "name": "portfolioVariance", + "description": "Calculate portfolio variance using O(n^2) covariance matrix multiplication", + "inputSchema": { + "type": "object", + "required": ["nAssets", "weights", "covarianceMatrix"], + "properties": { + "nAssets": {"type": "integer", "minimum": 2, "maximum": 2000}, + "weights": {"type": "array", "items": {"type": "number"}}, + "covarianceMatrix": {"type": "array", "items": {"type": "array", "items": {"type": "number"}}}, + "normalizeWeights": {"type": "boolean", "default": false}, + "nPeriodsPerYear": {"type": "integer", "default": 252} + } + }, + "endpoint": "POST /services/FinancialBenchmarkService/portfolioVariance", + "x-axis2-payloadTemplate": "{\"portfolioVariance\":[{\"arg0\":{}}]}", "x-requiresAuth": true, "annotations": { - "readOnlyHint": false, + "readOnlyHint": true, "destructiveHint": false, - "idempotentHint": false, + "idempotentHint": true, "openWorldHint": false } } @@ -161,7 +177,7 @@ before calling any tool:</p> <tr><th>Field</th><th>Type</th><th>Notes</th></tr> <tr><td><code>name</code></td><td>string</td><td>Axis2 operation name (local part of QName); use as tool name in MCP</td></tr> <tr><td><code>description</code></td><td>string</td><td>Auto-generated "ServiceName: operationName" — not a rich natural language description</td></tr> -<tr><td><code>inputSchema</code></td><td>object</td><td>MCP-compliant JSON Schema wrapper; <strong>properties is always empty</strong> (see Section 7)</td></tr> +<tr><td><code>inputSchema</code></td><td>object</td><td>MCP-compliant JSON Schema; populated from <code>mcpInputSchema</code> parameter in services.xml when set, otherwise empty <code>{}</code></td></tr> <tr><td><code>endpoint</code></td><td>string</td><td>Full POST path for this operation</td></tr> <tr><td><code>x-axis2-payloadTemplate</code></td><td>string (JSON)</td><td>The exact body to send, with the operation's wrapper already filled in</td></tr> <tr><td><code>x-requiresAuth</code></td><td>boolean</td><td><code>false</code> only for <code>loginService</code> (case-insensitive); <code>true</code> for everything else</td></tr> @@ -470,8 +486,8 @@ Each item notes whether the gap is architectural (won't be added to Axis2) or de <tr><th>Feature</th><th>Status</th><th>Notes</th></tr> <tr> <td>Rich <code>inputSchema</code> properties</td> - <td>Not implemented — architectural gap</td> - <td><code>inputSchema.properties</code> is always <code>{}</code>. Axis2 does not introspect Java parameter types into JSON Schema. MCP clients that need parameter validation must define their own schemas (e.g., via Pydantic models in a Python MCP server layer).</td> + <td><strong>Implemented</strong> — set <code>mcpInputSchema</code> parameter on <code><operation></code> in services.xml</td> + <td>When <code>mcpInputSchema</code> is set, the catalog embeds the full JSON Schema (types, constraints, required fields). Falls back to empty <code>{}</code> when not set. All financial benchmark operations have full schemas. Automatic introspection from Java types is not yet implemented — schemas are hand-authored in services.xml.</td> </tr> <tr> <td>Natural language tool descriptions</td> @@ -546,7 +562,7 @@ uses determines what limitations apply:</p> <tr><td>Query semantics</td><td>Per-operation parameters in arg0</td><td>Uniform filter/sort/fields on every resource</td></tr> <tr><td>Error format</td><td>SOAP fault with correlation ID UUID</td><td>RFC 7807 Problem Details (JSON, per-field)</td></tr> <tr><td>Pagination</td><td>Full result sets only</td><td>Cursor-based</td></tr> -<tr><td>inputSchema</td><td>Always empty properties</td><td>Full JSON Schema from OpenAPI annotations</td></tr> +<tr><td>inputSchema</td><td>Full JSON Schema via <code>mcpInputSchema</code> in services.xml (hand-authored)</td><td>Full JSON Schema from OpenAPI annotations (auto-generated)</td></tr> </table> <p>The Axis2 MCP catalog at <code>/openapi-mcp.json</code> provides MCP-ready tool @@ -561,7 +577,8 @@ tool discovery during the transition period.</p> <p>When building a Python MCP server that targets Axis2 services, keep these points in mind:</p> <ul> -<li>The Axis2 catalog's <code>inputSchema.properties</code> is always empty — define full +<li>When <code>mcpInputSchema</code> is set in services.xml, the catalog provides full + JSON Schema for each tool. For services without <code>mcpInputSchema</code>, define Pydantic <code>inputSchema</code> per tool in your Python MCP server layer.</li> <li>Use curated natural language descriptions in your MCP server rather than relying on the auto-generated "ServiceName: opName" default (or set <code>mcpDescription</code>
