# MCP Examples: Financial Services on Axis2/Java

**Summary**: Apache Axis2/Java serves the same financial calculations as Axis2/C —
portfolio variance, Monte Carlo VaR (GBM and Merton jump-diffusion), scenario
analysis — over JSON on WildFly 32/39 and Tomcat 11 with Spring Security JWT
authentication. This document shows the same live demos as the Axis2/C
`MCP_EXAMPLES.md`, run against the Java implementation, with head-to-head
performance numbers.

The financial results are identical (same algorithms, same inputs, same outputs).
The implementations compete only on performance.

---

## Transport and Timing Note

Both Axis2/C and Axis2/Java support **HTTPS/HTTP2**. Axis2/C runs over
Apache httpd with mod_h2; Axis2/Java runs over WildFly or Tomcat with
ALPN-negotiated HTTP/2 on port 8443. Verified on WildFly 32, WildFly 39,
and Tomcat 11 — all negotiate `h2` via ALPN when accessed over TLS.

All timings in this document use the **server-reported `calcTimeUs` field**
— wall-clock time measured inside the service handler, after request
parsing and before response serialization. Transport overhead (TLS, HTTP/2
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 --http2 -k https://localhost:8443/axis2-json-api/services/loginService \
  -H 'Content-Type: application/json' \
  -d '{"doLogin":[{"arg0":{"email":"java-dev@axis.apache.org","credentials":"userguide"}}]}' \
  | python3 -c "import sys,json; print(json.load(sys.stdin)['response']['token'])")
```

All subsequent examples assume `$TOKEN` is set.

---

## API Differences: Java vs C

The financial calculations are identical. The wire format differs:

| | Axis2/C | Axis2/Java |
|---|---|---|
| URL pattern | `.../portfolioVariance` | `.../FinancialBenchmarkService` |
| Request format | `{"n_assets": 5, ...}` | `{"portfolioVariance":[{"arg0":{...}}]}` |
| Response format | `{"status": "SUCCESS", ...}` | `{"response": {"status": "SUCCESS", ...}}` |
| Field naming | `snake_case` | `camelCase` |
| Authentication | None (HTTP/2 + TLS) | JWT Bearer token |
| Memory field | `memory_used_kb` (KB) | `memoryUsedMb` (MB) |
| Covariance input | Flat array (row-major) | 2D array `[[...],[...]]` |

---

## MCP Bridge

Axis2/Java exposes MCP via `axis2-mcp-bridge`, a stdio JAR that reads
`/openapi-mcp.json` and proxies `tools/call` to the Axis2 service. The
bridge handles authentication (mTLS on Tomcat, JWT on WildFly) so the AI
client sees only standard MCP JSON-RPC.

**Claude Desktop configuration** (WildFly, JWT auth):
```json
{
  "mcpServers": {
    "axis2-java-finbench": {
      "command": "java",
      "args": ["-jar", "/path/to/axis2-mcp-bridge-2.0.1-SNAPSHOT-exe.jar",
               "--base-url", "https://localhost:8443/axis2-json-api"]
    }
  }
}
```

**MCP stdio call format** (what the bridge sends/receives):
```bash
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 https://localhost:8443/axis2-json-api
```

All curl examples below include paired MCP stdio equivalents.

---

## Live Examples (Tested on WildFly 32/39 and Tomcat 11)

### Portfolio Variance — 5 assets

```bash
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,
    "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
  }}]}'
```

```json
{
    "response": {
        "status": "SUCCESS",
        "portfolioVariance": 0.0392,
        "portfolioVolatility": 0.198,
        "annualizedVolatility": 3.143,
        "calcTimeUs": 1,
        "matrixOperations": 25,
        "memoryUsedMb": 198,
        "runtimeInfo": "Java (JVM heap tier: < 2 GB)"
    }
}
```

**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 https://localhost:8443/axis2-json-api
```

### Portfolio Variance — 500 assets

```bash
# Generate 500-asset test data
python3 -c "
import json
n=500; w=[1.0/n]*n; c=[]
for i in range(n):
    row=[]
    for j in range(n):
        if i==j: row.append(0.04)
        else: row.append(0.01*max(0,1.0-abs(i-j)/50.0))
    c.append(row)
print(json.dumps({'portfolioVariance':[{'arg0':{'nAssets':n,'weights':w,'covarianceMatrix':c}}]}))" \
  > /tmp/pv500.json

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
```

```json
{
    "response": {
        "status": "SUCCESS",
        "portfolioVariance": 0.001027,
        "portfolioVolatility": 0.0320,
        "calcTimeUs": 660,
        "matrixOperations": 250000,
        "memoryUsedMb": 229
    }
}
```

(MCP equivalent omitted for 500-asset — the arguments object is identical,
just wrapped in `tools/call` JSON-RPC as shown above.)

### Monte Carlo VaR — 100K simulations

Monte Carlo Value at Risk estimates portfolio loss at a given confidence
level by simulating thousands of random price paths. The default model is
Geometric Brownian Motion (GBM): `S(t+dt) = S(t) × exp((μ − σ²/2)·dt + σ·√dt·Z)`
where Z ~ N(0,1). A Merton jump-diffusion model is also available
(`"model":"merton"`) which adds Poisson-distributed jumps for fat-tailed
scenarios — configurable via `jumpIntensity`, `jumpMean`, and `jumpVol`
parameters. Run 100,000 paths, sort the terminal values, read off the
1st percentile loss — that's your 99% VaR. Production risk systems run
this nightly for regulatory capital calculations.

```bash
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.198,
    "nPeriodsPerYear": 252
  }}]}'
```

```json
{
    "response": {
        "status": "SUCCESS",
        "meanFinalValue": 1104699.76,
        "var95": 219309.63,
        "var99": 317526.89,
        "cvar95": 279538.64,
        "maxDrawdown": 0.567,
        "probProfit": 0.657,
        "calcTimeUs": 1380378,
        "simulationsPerSecond": 72443,
        "memoryUsedMb": 142
    }
}
```

**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 https://localhost:8443/axis2-json-api
```

---

## Demo 1: Stress-test — "What if correlations spike?"

Same test as Axis2/C `MCP_EXAMPLES.md` Demo 1. Baseline portfolio at real
market correlations, then stressed to ρ = 0.8, then Monte Carlo on the
stressed portfolio.

Each curl below has an MCP equivalent — same `tools/call` pattern as
the Live Examples above, with the arguments object matching the `arg0`
payload. The bridge handles the Axis2 JSON-RPC wrapping transparently.

**Step 1 — Baseline:**

```bash
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,
    "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
  }}]}'
```

```json
{
    "response": {
        "status": "SUCCESS",
        "portfolioVariance": 0.0392,
        "portfolioVolatility": 0.198,
        "calcTimeUs": 1,
        "memoryUsedMb": 198
    }
}
```

**Step 2 — Stressed (all pairwise correlations → 0.8):**

```bash
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,
    "weights": [0.25, 0.25, 0.20, 0.15, 0.15],
    "covarianceMatrix": [
      [0.0691, 0.0656, 0.0730, 0.0530, 0.0366],
      [0.0656, 0.0974, 0.0866, 0.0629, 0.0434],
      [0.0730, 0.0866, 0.1204, 0.0699, 0.0483],
      [0.0530, 0.0629, 0.0699, 0.0635, 0.0351],
      [0.0366, 0.0434, 0.0483, 0.0351, 0.0303]
    ],
    "normalizeWeights": true
  }}]}'
```

```json
{
    "response": {
        "status": "SUCCESS",
        "portfolioVariance": 0.0649,
        "portfolioVolatility": 0.2547,
        "calcTimeUs": 1,
        "memoryUsedMb": 198
    }
}
```

**Step 3 — Monte Carlo on stressed portfolio (100K paths):**

```bash
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.255,
    "nPeriodsPerYear": 252
  }}]}'
```

```json
{
    "response": {
        "status": "SUCCESS",
        "meanFinalValue": 1104718.26,
        "var95": 296582.35,
        "var99": 409644.96,
        "cvar95": 364494.42,
        "maxDrawdown": 0.668,
        "probProfit": 0.602,
        "calcTimeUs": 1437421,
        "simulationsPerSecond": 69569
    }
}
```

**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 https://localhost:8443/axis2-json-api
```

**Comparison — Axis2/C vs Axis2/Java (same inputs, same day):**

| Metric | Normal ρ | Stressed ρ = 0.8 | Change |
|--------|----------|-------------------|--------|
| Portfolio vol | 19.8% | 25.5% | **+29%** |
| 95% VaR (1yr, $1M) | $219K | $297K | **+$78K** |
| 99% VaR | $318K | $410K | **+$92K** |
| Prob of profit | 65.7% | 60.2% | -5.5pp |

| Timing | Axis2/C | Axis2/Java | Ratio |
|--------|---------|------------|-------|
| `portfolioVariance` (×2) | < 1 μs each | 1 μs each | ~1x |
| `monteCarlo` (100K) | 727 ms | 1,437 ms | **2.0x** |
| Total compute | ~0.73 sec | ~1.44 sec | 2.0x |

Both produce the same financial results. Java's Monte Carlo is ~2x slower
on this run; the JIT-warmed steady state is typically 1.3-1.5x (see
convergence section below).

---

## Demo 2: Pre-trade risk — "Should I add this name?"

Same test as Axis2/C Demo 2. Two candidate 6-asset portfolios: European
semiconductor (high correlation to existing tech) vs Japanese peer (low
correlation). All calls have MCP equivalents via the bridge (same pattern
as Live Examples).

**Candidate A — European semi (vol 44%, ρ = 0.68 to tech):**

```bash
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,
    "weights": [0.2425, 0.2425, 0.194, 0.1455, 0.1455, 0.03],
    "covarianceMatrix": [
      [0.0691, 0.0313, 0.0457, 0.0272,-0.0035, 0.0787],
      [0.0313, 0.0976, 0.0591, 0.0408, 0.0058, 0.0934],
      [0.0457, 0.0591, 0.1207, 0.0437,-0.0086, 0.1039],
      [0.0272, 0.0408, 0.0437, 0.0638, 0.0015, 0.0610],
      [-0.0035, 0.0058,-0.0086, 0.0015, 0.0303, 0.0115],
      [0.0787, 0.0934, 0.1039, 0.0610, 0.0115, 0.1936]
    ],
    "normalizeWeights": true
  }}]}'
```

```json
{"response": {"status": "SUCCESS", "portfolioVolatility": 0.2035, "calcTimeUs": 1}}
```

**Candidate B — Japanese peer (vol 38%, ρ = 0.31 to US tech):**

```bash
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,
    "weights": [0.2425, 0.2425, 0.194, 0.1455, 0.1455, 0.03],
    "covarianceMatrix": [
      [0.0691, 0.0313, 0.0457, 0.0272,-0.0035, 0.0310],
      [0.0313, 0.0976, 0.0591, 0.0408, 0.0058, 0.0368],
      [0.0457, 0.0591, 0.1207, 0.0437,-0.0086, 0.0409],
      [0.0272, 0.0408, 0.0437, 0.0638, 0.0015, 0.0239],
      [-0.0035, 0.0058,-0.0086, 0.0015, 0.0303, 0.0066],
      [0.0310, 0.0368, 0.0409, 0.0239, 0.0066, 0.1444]
    ],
    "normalizeWeights": true
  }}]}'
```

```json
{"response": {"status": "SUCCESS", "portfolioVolatility": 0.1968, "calcTimeUs": 1}}
```

**Head-to-head Monte Carlo (100K paths each):**

```bash
# European candidate (vol 21.1%)
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 --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,
       "nPeriodsPerYear":252}}]}'
```

**European candidate response:**
```json
{"response": {"var95": 237481, "var99": 340245, "cvar95": 300412, "probProfit": 0.643, "maxDrawdown": 0.610, "calcTimeUs": 1360351}}
```

**Japanese candidate response:**
```json
{"response": {"var95": 221367, "var99": 322087, "cvar95": 282371, "probProfit": 0.656, "maxDrawdown": 0.555, "calcTimeUs": 1364834}}
```

**Results summary (2026-04-08):**

| | Before (5 names) | + European semi | + Japanese peer |
|---|---|---|---|
| Portfolio vol | 19.8% | **20.3%** (+55bp) | **19.7%** (-13bp) |
| 95% VaR ($1M) | $219K | $237K | $221K |
| 99% VaR | $318K | $340K | $322K |
| CVaR 95% | $280K | $300K | $282K |
| Prob of profit | 65.7% | 64.3% | 65.6% |

**Timing comparison:**

| Call | Axis2/C | Axis2/Java | Ratio |
|------|---------|------------|-------|
| `portfolioVariance` (×4) | < 1 μs each | 1 μs each | ~1x |
| `monteCarlo` European | 716 ms | 1,360 ms | 1.9x |
| `monteCarlo` Japanese | 672 ms | 1,365 ms | 2.0x |
| Total compute | ~1.4 sec | ~2.7 sec | 1.9x |

Financial conclusions are identical — the Japanese name provides genuine
diversification. Java takes roughly twice as long for the Monte Carlo
simulations.

---

## Demo 3: Convergence — "How much compute do I actually need?"

Run `monteCarlo` at 1K, 10K, 100K, and 1M paths:

```bash
for N in 1000 10000 100000 1000000; do
  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,
         \"nPeriodsPerYear\":252}}]}"
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 https://localhost:8443/axis2-json-api
```

**Axis2/Java results (2026-04-08):**

| Simulations | 95% VaR | 99% VaR | Calc time | Sims/sec |
|-------------|---------|---------|-----------|----------|
| 1,000 | $221,665 | $325,340 | **13 ms** | 77,863 |
| 10,000 | $216,407 | $312,895 | **136 ms** | 73,378 |
| 100,000 | $218,868 | $315,163 | **1.37 sec** | 73,211 |
| 1,000,000 | $217,286 | $315,700 | **13.8 sec** | 72,710 |

**Head-to-head with Axis2/C (same inputs, same machine):**

| Simulations | C time | Java time | Ratio | C sims/sec | Java sims/sec |
|-------------|--------|-----------|-------|------------|---------------|
| 1,000 | 6 ms | 13 ms | 2.1x | 164,295 | 77,863 |
| 10,000 | 66 ms | 136 ms | 2.1x | 152,423 | 73,378 |
| 100,000 | 716 ms | 1,370 ms | 1.9x | 139,650 | 73,211 |
| 1,000,000 | 6.6 sec | 13.8 sec | 2.1x | 150,773 | 72,710 |

The ratio is a consistent **~2x** across all simulation counts. C processes
~150K simulations/sec vs Java's ~73K sims/sec.

**Production capacity math (Java)**: at 1.37 sec per 100K-path run, a single
core processes **44 funds per minute**. A 500-fund universe completes in
~11.4 minutes on one core, or **~69 seconds on a 10-core node**.

For comparison, Axis2/C: 500 funds in 6 minutes on one core, 36 seconds
on 10 cores.

---

## 500-Asset Portfolio Variance — The Big Comparison

This is where the gap widens. O(n^2) matrix math at n=500 means 250,000
multiply-accumulate operations on a flat array (C) vs a 2D Java array
with bounds checking.

**Axis2/C:**
```json
{"portfolio_volatility": 0.0320, "calc_time_us": 232, "matrix_operations": 250000}
```

**Axis2/Java:**
```json
{"portfolioVolatility": 0.0320, "calcTimeUs": 660, "matrixOperations": 250000}
```

| | Axis2/C | Axis2/Java | Ratio |
|---|---|---|---|
| Calc time | **232 μs** | **660 μs** | 2.8x |
| Memory | ~193 MB RSS | 229 MB heap | 1.2x |
| Result | 0.0320 | 0.0320 | identical |

At 500 assets Java is 2.8x slower — the JVM's array bounds checking and
object overhead becomes measurable at O(n^2). Both are still sub-millisecond,
which is fast enough for interactive use.

---

## Full Performance Summary

All measurements from 2026-04-08, same machine (Linux, 32 GB RAM).
Timings are server-reported `calcTimeUs` — pure computation time, no
transport overhead. Monte Carlo timings vary ±5% across runs due to JIT
warmup and GC; values below are from the Demo 3 convergence runs (JIT-warm
steady state).

| Benchmark | Axis2/C | Axis2/Java | Ratio |
|-----------|---------|------------|-------|
| portfolioVariance (5 assets) | < 1 μs | 1 μs | ~1x |
| portfolioVariance (500 assets) | 232 μs | 660 μs | 2.8x |
| monteCarlo (1K × 252) | 6 ms | 13 ms | 2.1x |
| monteCarlo (10K × 252) | 66 ms | 136 ms | 2.1x |
| monteCarlo (100K × 252) | 716 ms | 1,366 ms | 1.9x |
| monteCarlo (1M × 252) | 6.6 sec | 13.8 sec | 2.1x |
| MC throughput (sims/sec) | ~150K | ~73K | 2.1x |
| Peak memory (500-asset PV) | ~193 MB | 229 MB | 1.2x |
| Peak memory (100K MC) | ~44 MB | 142 MB | 3.2x |
| Startup | instant | ~7 sec (WildFly) | N/A |

### When to use which

- **Axis2/C**: Edge devices, Android (1-2 GB RAM), IoT gateways, latency-critical
  paths, environments where a JVM cannot run or its memory overhead is unacceptable.
  Sub-millisecond portfolio variance at 500 assets. Startup in milliseconds.

- **Axis2/Java**: Standard Java EE/Jakarta EE deployment on WildFly or Tomcat,
  teams with existing Java infrastructure, environments requiring Spring Security
  (JWT/mTLS), or integration with Java-based data providers. 2x slower on Monte
  Carlo but still interactive (1.4 sec for 100K paths). Deploys as a standard WAR
  with OpenAPI/Swagger UI and MCP bridge included.

Both implement the same MCP tool schemas. An AI assistant configured with
either backend gets the same financial capabilities — the same questions
produce the same answers. The choice is deployment context, not functionality.

---

## MCP Tool Discovery

Axis2/Java exposes an MCP tool catalog at:

```
GET https://localhost:8443/axis2-json-api/openapi-mcp.json
```

This endpoint returns the same tool schema structure that Claude Desktop
and other MCP clients consume. The catalog includes `doLogin`,
`portfolioVariance`, `monteCarlo`, and `scenarioAnalysis` — each with full
input schemas, parameter types, constraints, and defaults. The three
financial tools are identical in capability to the 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":"java-dev@axis.apache.org","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":"java-dev@axis.apache.org","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 Deployment Notes

See `WILDFLY32_DEPLOY_STATE.md` in the Axis2/C repo for the full deployment
walkthrough. Key points (apply to both WildFly 32 and WildFly 39):

- WildFly 32.0.1.Final or WildFly 39 with `--add-modules=java.se` in `standalone.conf`
- `jboss-deployment-structure.xml` from production deployment template (includes `jdk.net` module dependency)
- `beans.xml` with `bean-discovery-mode="none"` (satisfies Weld without CDI scanning)
- Spring Boot 3.4.3 starts in ~0.9 seconds inside WildFly
- WAR: `axis2-json-api-0.0.1-SNAPSHOT.war`
