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 ad14246daeba98abfdcf4f5edcececd5764bcfb8 Author: Robert Lazarski <[email protected]> AuthorDate: Mon Apr 6 06:22:10 2026 -1000 Add MCP development plan and Axis2 modernization roadmap - MCP.md: Full MCP implementation plan capturing current development state — Track A (OpenAPI-driven bridge: A1 /openapi-mcp.json endpoint, A2 stdio bridge JAR, A3 team validation, A4 HTTP/SSE) and Track B (native axis2-transport-mcp, stdio first then HTTP/SSE). Includes design decisions, build dependencies, and immediate next actions. - AXIS2_MODERNIZATION_PLAN.md: 7-phase modernization plan (Spring Boot starter, OpenAPI annotation bridge, REST dual-protocol, MCP bridge, HTTP/2 publication, native MCP transport, community positioning) Co-Authored-By: Claude Sonnet 4.6 <[email protected]> --- AXIS2_MODERNIZATION_PLAN.md | 432 ++++++++++++++++++++++++++++++++++++++++++++ MCP.md | 272 ++++++++++++++++++++++++++++ 2 files changed, 704 insertions(+) diff --git a/AXIS2_MODERNIZATION_PLAN.md b/AXIS2_MODERNIZATION_PLAN.md new file mode 100644 index 0000000000..7e0242f4c0 --- /dev/null +++ b/AXIS2_MODERNIZATION_PLAN.md @@ -0,0 +1,432 @@ +--- +type: architecture +created: 2026-04-06 +status: Active +--- + +# Axis2/Java Modernization Plan + +**BLUF**: Axis2 becomes a multi-protocol service platform — one service implementation +serving JSON-RPC (existing callers), REST (Data API consumers), and MCP (AI agents) +simultaneously. The Spring Boot starter removes adoption tax. OpenAPI generation makes +every Axis2 service AI-discoverable. A native MCP transport eliminates the wrapper layer +entirely. No other Java framework can do all three from the same service deployment. + +**Foundation already in place**: +- `springbootdemo-tomcat11` — working reference implementation (Spring Boot 3.x + Axis2 + + Tomcat 11 + Java 25) +- `axis2-openapi` module — OpenAPI spec served at `/openapi.json`, `/openapi.yaml`, + `/swagger-ui` +- `modules/transport-h2` — HTTP/2 transport module (proof of concept, tested) +- ThreadPool instance-field fix committed (`27860ddf9f`) +- Java 25 + Tomcat 11.0.20 full end-to-end test passing + +--- + +## Phase 1 — Spring Boot Starter + +**Goal**: Reduce Axis2 + Spring Boot integration from a multi-day configuration project +to a single Maven dependency. + +**Problem today**: The `springbootdemo-tomcat11` project is a hand-rolled integration +requiring `maven-antrun-plugin` WAR pre-staging, manual `.mar` module file deployment, +explicit `Axis2WebAppInitializer`, and custom security filter chain wiring. Every new +Axis2+Spring Boot project repeats this work and gets it slightly wrong. + +### Tasks + +1. **Create `axis2-spring-boot-starter` module** in `modules/` + - Spring Boot autoconfiguration class (`Axis2AutoConfiguration`) + - Auto-registers `AxisServlet` at configurable path (default `/services/*`) + - Classpath scanning for `.aar` and `.mar` modules — no manual staging + - Externalized configuration via `application.properties`: + ```properties + axis2.services-path=/services + axis2.repository-path=classpath:axis2-repository + axis2.rest.enabled=true + axis2.openapi.enabled=true + ``` + +2. **Spring Security autoconfiguration** + - Default `SecurityFilterChain` bean wired to Axis2 service paths + - `RequestAndResponseValidatorFilter` registered automatically + - Overridable — consuming apps provide their own `SecurityFilterChain` bean to replace + +3. **Logging bridge autoconfiguration** + - Log4j2 → SLF4J bridge wired without manual configuration + - `log4j2-spring.xml` loaded automatically from classpath + +4. **WAR and embedded container support** + - Works both as embedded (Spring Boot `main()`) and as WAR deployed to Tomcat/WildFly + - `SpringBootServletInitializer` extension handled by the starter + +5. **Starter test suite** + - Integration test: Spring Boot app with starter dependency, single `@WebService`, + confirms service reachable at `/services/{name}` + - Test matrix: Java 21, Java 25 × embedded Tomcat, external Tomcat 11, WildFly 32 + +### Deliverable +`axis2-spring-boot-starter-2.x.x.jar` — add to `pom.xml`, Axis2 works. Zero XML +configuration required for the common case. + +### Dependency +None — builds directly on `springbootdemo-tomcat11` as the reference implementation. + +--- + +## Phase 2 — OpenAPI Generation (springdoc-openapi Bridge) + +**Goal**: Every Axis2 service automatically produces an OpenAPI 3.1 spec from Java +annotations. MCP tool definitions are generated from that spec at no additional cost. + +**Problem today**: `axis2-openapi` generates a spec from Axis2service descriptors +(`services.xml`), not from Java type annotations. The spec is structural but not +semantically rich — no operation descriptions, no parameter constraints, no response +schemas beyond what Axis2 infers. springdoc-openapi generates far richer specs from +`@Operation`, `@Parameter`, `@ApiResponse` annotations on the Java class itself. + +### Tasks + +1. **Annotation support on Axis2 `@WebService` classes** + - Axis2 services annotated with springdoc/Swagger annotations: + ```java + @WebService + public class AssetCalculationsService { + + @Operation(summary = "Get portfolio calculations", + description = "Returns PWR, OPS, Kelly weight for all assets in a fund") + @ApiResponse(responseCode = "200", content = @Content(schema = + @Schema(implementation = AssetCalculationsResponse.class))) + public AssetCalculationsResponse doGetAssetCalculations( + @Parameter(description = "Fund ID") AssetCalculationsRequest request) { ... } + } + ``` + - Annotations processed by `axis2-openapi` during spec generation + - Falls back to structural inference when annotations absent (backward compatible) + +2. **Java type → JSON Schema generation** + - Request/response POJOs introspected to produce `components/schemas` in the spec + - Uses Jackson's `JsonSchemaGenerator` or springdoc's `ModelConverter` pipeline + - Handles: nested objects, arrays, enums, `BigDecimal` as `string` with `format: decimal` + +3. **OpenAPI 3.1 output** + - Upgrade `axis2-openapi` output from OpenAPI 3.0 to OpenAPI 3.1 + - 3.1 required for full JSON Schema compatibility (needed for MCP tool `inputSchema`) + +4. **MCP tool definition export endpoint** + - `GET /openapi-mcp.json` — returns MCP-formatted tool definitions derived from the + OpenAPI spec: + ```json + { + "tools": [ + { + "name": "doGetAssetCalculations", + "description": "Get portfolio calculations — PWR, OPS, Kelly weight", + "inputSchema": { + "type": "object", + "properties": { + "fundID": { "type": "integer" }, + "departmentID": { "type": "integer" } + }, + "required": ["fundID", "departmentID"] + } + } + ] + } + ``` + - Served by `OpenApiServlet` alongside existing `/openapi.json` and `/swagger-ui` + +5. **Starter integration** + - `axis2.openapi.enabled=true` in starter autoconfiguration activates both + `/openapi.json` and `/openapi-mcp.json` endpoints automatically + +### Deliverable +Any Axis2 service annotated with standard OpenAPI annotations produces a spec and MCP +tool definitions served at known endpoints. An MCP wrapper (Phase 4) can point at +`/openapi-mcp.json` and expose every Axis2 service as an AI tool with zero additional +code. + +### Dependency +Phase 1 (starter) — OpenAPI endpoints auto-registered via starter autoconfiguration. + +--- + +## Phase 3 — REST Transport (Dual-Protocol Services) + +**Goal**: The same Axis2 `@WebService` class is reachable via both its existing +JSON-RPC path and a new REST path, with proper HTTP method semantics and +resource-oriented URLs. + +**Problem today**: RAPI's service URLs (`POST /services/getAssetCalculationsService/ +doGetAssetCalculationsJob`) are JSON-RPC over HTTP. New consumers (Data API, React +frontend, MCP agents) expect `GET /api/v1/funds/{id}/calculations`. Axis2 has REST +dispatch capability in `axis2.xml` but it has never been activated or documented for +modern Spring Boot deployments. + +### Tasks + +1. **REST dispatcher activation and configuration** + - Enable Axis2 REST dispatcher in autoconfiguration: + ```properties + axis2.rest.enabled=true + axis2.rest.base-path=/api/v1 + ``` + - REST dispatcher maps `GET /api/v1/funds/{id}/calculations` → + `AssetCalculationsService.doGetAssetCalculations(fundId)` + +2. **URL template annotation** + - New `@RestMapping` annotation (or reuse JAX-RS `@GET`/`@Path` if feasible): + ```java + @RestMapping(method = "GET", path = "/funds/{fundId}/calculations") + public AssetCalculationsResponse doGetAssetCalculations( + @PathParam("fundId") long fundId, + @QueryParam("fields") String fields) { ... } + ``` + - Axis2 REST dispatcher resolves path variables and query parameters from the + URL before invoking the service operation + +3. **HTTP method routing** + - GET → read operations (no side effects) + - POST → create operations + - PUT/PATCH → update operations + - DELETE → delete operations + - Method constraint enforced by REST dispatcher (405 Method Not Allowed if violated) + +4. **Parallel transports — same service, no duplication** + - JSON-RPC path unchanged: `POST /services/AssetCalculationsService/ + doGetAssetCalculations` + - REST path added: `GET /api/v1/funds/{id}/calculations` + - Both routes to the same Java method — no code duplication + - Handler chain (security, logging, validation) applies to both + +5. **OpenAPI spec reflects REST paths** + - Phase 2 spec generator emits REST paths (not JSON-RPC paths) when `@RestMapping` + present + - Both paths optionally included with `x-axis2-jsonrpc-path` extension field for + tooling that needs the RPC form + +6. **Integration tests** + - Confirm same service reachable at both paths + - Confirm handler chain (authentication, validation) applies identically to both + - Test matrix includes Java 21, 25 and Tomcat 11 + embedded Tomcat + +### Deliverable +Existing Axis2 services add `@RestMapping` annotations and are immediately available +as REST endpoints alongside their JSON-RPC paths. RAPI services can be exposed to Data +API consumers without rewriting or duplicating service logic. + +### Dependency +Phase 1 (starter registers both dispatchers), Phase 2 (REST paths appear in OpenAPI +spec and MCP tool definitions). + +--- + +## Phase 4 — MCP Path 1: OpenAPI-Driven MCP Wrapper + +**Goal**: Package a lightweight MCP server that reads an Axis2 service's OpenAPI spec +and exposes every operation as an MCP tool. AI agents (Claude, etc.) can call Axis2 +services via MCP with no MCP-specific code in the service itself. + +**This is the practical MCP path available immediately after Phase 2.** + +### Tasks + +1. **`axis2-mcp-bridge` module** + - Thin Spring Boot app (or embeddable library) that: + - Reads `/openapi-mcp.json` from a configured Axis2 deployment + - Implements MCP `initialize` handshake, reporting tool capabilities + - Forwards MCP `tools/call` requests to the corresponding Axis2 REST endpoint + (Phase 3) or JSON-RPC endpoint (fallback if Phase 3 not deployed) + - Returns MCP-formatted responses + +2. **Transport: HTTP + SSE** + - MCP HTTP transport: POST to `/mcp` for client→server messages + - SSE endpoint at `/mcp/events` for server→client streaming + - Spring's `SseEmitter` for SSE — standard Spring MVC, no Axis2 involvement + +3. **Configuration** + - `axis2.mcp.target-url=http://localhost:8080/axis2-json-api` points bridge at the + Axis2 deployment + - Bridge refreshes tool definitions on startup and on `/openapi-mcp.json` change + +4. **Starter integration** + - `axis2.mcp.bridge.enabled=true` in starter spins up the bridge in the same JVM + as the Axis2 deployment — no separate process needed for simple deployments + +5. **Reference implementation** + - Extend `springbootdemo-tomcat11` with MCP bridge enabled + - Document: Claude Desktop config pointing at the bridge, example tool call flow + +### Deliverable +`axis2-mcp-bridge` — configure, deploy, and every Axis2 service is callable from Claude +Desktop, Claude API tool use, or any MCP-compatible AI agent. No MCP code in service +classes. + +### Dependency +Phase 2 (requires `/openapi-mcp.json` endpoint). Phase 3 (REST paths preferred as MCP +call targets, but JSON-RPC fallback works without Phase 3). + +--- + +## Phase 5 — HTTP/2 Transport Publication + +**Goal**: `modules/transport-h2` becomes a supported, tested, documented module with +a published performance benchmark. + +**Foundation**: The module exists and was tested end-to-end with Java 25 + Tomcat 11.0.20 +in `springbootdemo-tomcat11` (`BigDataH2Service` — confirmed working with `datasetId` + +`datasetSize` request fields). + +### Tasks + +1. **Formal integration test suite for `transport-h2`** + - Tests against: embedded Tomcat (Spring Boot), external Tomcat 10, Tomcat 11, + WildFly 32 + - Java versions: 21, 25 + - Large payload test: confirm HTTP/2 multiplexing benefit over HTTP/1.1 at 1MB+ + payloads + +2. **Performance benchmark** + - Baseline: HTTP/1.1 transport, sequential requests, 1MB / 10MB / 50MB payloads + - Compare: HTTP/2 transport, concurrent requests (multiplexing) + - Document results in module README + +3. **Starter integration** + - `axis2.transport.h2.enabled=true` activates HTTP/2 transport in the starter + - Auto-detects servlet container HTTP/2 support (Tomcat 10+, WildFly 32+) + +4. **Module graduation** + - Move from `modules/transport-h2` proof-of-concept to a released artifact at the + same version as the core modules + - Javadoc, usage example, known limitations documented + +### Deliverable +`axis2-transport-h2-2.x.x.jar` as a supported module. HTTP/2 is a documented, tested +deployment option for Axis2 services with large payloads. + +### Dependency +Phase 1 (starter exposes the transport config property). No dependency on Phases 2-4. + +--- + +## Phase 6 — Native MCP Transport (`axis2-transport-mcp`) + +**Goal**: Axis2 speaks MCP natively. An MCP client (Claude Desktop, Claude API, any +MCP-compatible agent) connects directly to Axis2 with no intermediate wrapper. One +service deployment, three protocols: JSON-RPC, REST, MCP. + +**This is the novel Apache project contribution — no other Java framework has this.** + +### Tasks + +1. **`axis2-transport-mcp` module** + - Implements Axis2 `TransportListener` and `TransportSender` interfaces + - Translates MCP JSON-RPC 2.0 messages ↔ Axis2 `MessageContext` + - MCP `tools/call` → Axis2 service operation invocation + - Axis2 response → MCP `tools/call` result + +2. **MCP initialize handshake** + - Axis2 responds to MCP `initialize` with: + - `serverInfo.name`: service deployment name from `axis2.xml` + - `capabilities.tools`: populated from deployed services + - Tool list derived from Phase 2 OpenAPI/MCP tool definitions + +3. **Transport: stdio (ships first)** + - stdio transport is simpler than HTTP/SSE — no persistent connection management + - Axis2 can be launched as a subprocess; Claude Desktop communicates via stdin/stdout + - Validates the JSON-RPC 2.0 translation layer before adding HTTP complexity + +4. **Transport: HTTP + SSE (ships second)** + - MCP HTTP transport layer on top of Axis2's existing HTTP infrastructure + - SSE for server-initiated messages (progress notifications for long-running calcs) + - Reuses Axis2's HTTP transport configuration (port, TLS, thread pool) + +5. **Tool schema generation** + - Uses Phase 2 JSON Schema generation to populate `inputSchema` for each tool + - Tool descriptions from `@Operation` annotations (Phase 2) + +6. **Starter integration** + - `axis2.transport.mcp.enabled=true` + - `axis2.transport.mcp.transport=stdio|http` + - HTTP transport: `axis2.transport.mcp.path=/mcp` + +7. **Integration test** + - MCP client (test harness, not full Claude) sends `initialize` + `tools/list` + + `tools/call` sequence + - Verifies correct JSON-RPC 2.0 framing, correct tool invocation, correct response + +### Deliverable +`axis2-transport-mcp-2.x.x.jar` — configure, and Axis2 becomes a native MCP server. +Phase 4 wrapper becomes optional (useful for external deployments; native transport +preferred for co-located services). + +### Dependency +Phase 2 (tool schema generation), Phase 1 (starter wires the transport). Phase 3 (REST) +independent — MCP transport calls service operations directly, REST paths not required. + +--- + +## Phase 7 — Community and Positioning + +**Goal**: The Apache community and downstream projects know these capabilities exist, +understand the multi-protocol positioning, and have concrete migration guides. + +### Tasks + +1. **Apache blog post: "Axis2 as a Multi-Protocol Service Platform"** + - Covers: dual-protocol JSON-RPC + REST from one service, OpenAPI generation, + MCP transport, Spring Boot starter + - Uses the calculation orchestration deployment (anonymized DPTv2) as the case study: + sub-200ms portfolio calculations, CDC cache, Node.js bridge + - Positions Axis2's handler chain as the differentiator for production orchestration + workloads + +2. **ThreadPool fix release note** + - Explicit note in 2.x changelog: `ThreadPool.shutDown` was a static field; changed + to instance field. Affects any deployment running multiple Axis2 engine instances + in the same JVM. Multi-pool deployments should upgrade. + +3. **`springbootdemo-tomcat11` as canonical reference** + - The existing module becomes the official Spring Boot + Axis2 + Tomcat 11 + reference implementation in the distribution + - README updated to reflect starter usage once Phase 1 ships + +4. **Migration guide: RAPI JSON-RPC → Dual-Protocol** + - Step-by-step: add `@RestMapping` annotations, enable REST dispatcher, verify + both paths, update OpenAPI spec, expose MCP tools + - Targets teams running Axis2 JSON-RPC who want REST and MCP without rewriting + +--- + +## Summary Timeline + +| Phase | Deliverable | Key Dependency | +|---|---|---| +| **1** | `axis2-spring-boot-starter` | springbootdemo-tomcat11 reference | +| **2** | OpenAPI annotation bridge + MCP tool export | Phase 1 | +| **3** | REST transport + dual-protocol services | Phase 1, Phase 2 | +| **4** | `axis2-mcp-bridge` (OpenAPI-driven MCP wrapper) | Phase 2 | +| **5** | `transport-h2` published module + benchmarks | Phase 1 | +| **6** | `axis2-transport-mcp` native MCP transport | Phase 2, Phase 1 | +| **7** | Community posts, migration guide, reference impl | All phases | + +Phases 1 and 2 are the critical path — everything else depends on them. Phases 3, 4, +and 5 can proceed in parallel after Phase 2. Phase 6 requires Phase 2 but is otherwise +independent of Phases 3, 4, and 5. + +--- + +## End State + +A single Axis2 service deployment, configured once, serves: + +``` +Claude Desktop / AI agent → MCP (native transport, Phase 6) + ↓ +Data API / React frontend → REST (Phase 3) ──► Axis2 Service + ↑ (one implementation) +Existing RAPI callers → JSON-RPC (unchanged) +``` + +With OpenAPI spec and MCP tool definitions auto-generated (Phase 2) and a Spring Boot +starter (Phase 1) that makes the whole stack a single Maven dependency. diff --git a/MCP.md b/MCP.md new file mode 100644 index 0000000000..540e749c2c --- /dev/null +++ b/MCP.md @@ -0,0 +1,272 @@ +--- +type: architecture +created: 2026-04-06 +status: Active — pre-implementation +--- + +# MCP Support for Apache Axis2/Java + +**BLUF**: Axis2/Java gains MCP (Model Context Protocol) support in two phases. Phase A +(practical, immediate) wraps an existing Axis2 deployment with a bridge that reads +`/openapi-mcp.json` and proxies MCP `tools/call` to Axis2 over HTTP. Phase B (native, +novel Apache contribution) implements `axis2-transport-mcp` so Axis2 speaks MCP +directly — no wrapper. One service deployment, three protocols: JSON-RPC, REST, MCP. + +MCP is JSON-RPC 2.0. The three required methods are `initialize`, `tools/list`, and +`tools/call`. Everything else (transport: stdio or HTTP/SSE, tool schema format, +capability negotiation) is specified by the MCP protocol document at +modelcontextprotocol.io. + +--- + +## Current State (2026-04-06) + +### What exists today + +| Artifact | Status | Notes | +|----------|--------|-------| +| `springbootdemo-tomcat11` | ✅ Working | Spring Boot 3.x + Axis2 + Tomcat 11 + Java 25, end-to-end tested | +| `axis2-openapi` module | ✅ Working | Serves `/openapi.json`, `/openapi.yaml`, `/swagger-ui` | +| `modules/transport-h2` | ✅ Tested | HTTP/2 transport PoC, `BigDataH2Service` confirmed working | +| ThreadPool instance-field fix | ✅ Committed | `27860ddf9f` — static→instance, fixes multi-pool JVM isolation | +| `axis2-spring-boot-starter` | ❌ Not started | Phase 1 of modernization plan | +| `/openapi-mcp.json` endpoint | ❌ Not started | Requires work in `axis2-openapi` module | +| `axis2-mcp-bridge` | ❌ Not started | Thin bridge JAR, reads MCP catalog, proxies to Axis2 | +| `axis2-transport-mcp` | ❌ Not started | Native MCP transport — novel Apache contribution | + +### Reference implementation + +``` +springbootdemo-tomcat11 base URL: http://localhost:8080/axis2-json-api +Services deployed: + - LoginService (auth) + - BigDataH2Service (streaming/multiplexing demo) +``` + +`BigDataH2Service` request format (confirmed working): +```json +{"processBigDataSet":[{"request":{"datasetId":"test-dataset-001","datasetSize":1048576}}]} +``` + +--- + +## Track A — OpenAPI-Driven MCP Bridge + +**When**: Immediate next work session. No dependency on native transport. + +**Why first**: The team already knows MCP. This gives them a working demo calling +existing Axis2 services through Claude/Cursor without writing MCP-specific service code. + +### A1 — `/openapi-mcp.json` endpoint in `axis2-openapi` + +**File**: `modules/openapi/src/main/java/org/apache/axis2/openapi/` + +Add `McpToolCatalogServlet` alongside the existing `OpenApiServlet`. Endpoint returns: + +```json +{ + "tools": [ + { + "name": "processBigDataSet", + "description": "Process a large dataset using HTTP/2 multiplexing", + "inputSchema": { + "type": "object", + "properties": { + "datasetId": { "type": "string" }, + "datasetSize": { "type": "integer" } + }, + "required": ["datasetId", "datasetSize"] + }, + "endpoint": "POST /services/BigDataH2Service/processBigDataSet" + } + ] +} +``` + +Implementation strategy: +- Inject `ConfigurationContext` via `getServletContext().getAttribute(AxisServlet.CONFIGURATION_CONTEXT)` +- Iterate `ctx.getAxisConfiguration().getServices()` → each `AxisService` +- Iterate `service.getOperations()` → each `AxisOperation` +- Use existing `axis2-openapi` reflection infrastructure for schema extraction +- Add optional `@McpTool(description = "...")` annotation for richer descriptions + +**Estimated effort**: 2–3 days. + +### A2 — `axis2-mcp-bridge` stdio server + +**Location**: New module `modules/mcp-bridge/` or standalone JAR. + +Startup (Claude Desktop `~/.config/claude/claude_desktop_config.json`): +```json +{ + "mcpServers": { + "axis2-demo": { + "command": "java", + "args": ["-jar", "/path/to/axis2-mcp-bridge.jar", + "--base-url", "http://localhost:8080/axis2-json-api"] + } + } +} +``` + +Core loop: +1. Fetch `{base-url}/openapi-mcp.json` at startup → build tool registry +2. Read JSON-RPC 2.0 lines from `System.in` +3. `initialize` → return server info + tool capabilities +4. `tools/list` → return registry +5. `tools/call` → `HttpClient.send(POST to Axis2 endpoint)` → return result +6. Write JSON-RPC 2.0 response to `System.out` + +Use the official MCP Java SDK to handle `initialize` capability negotiation rather than +hand-rolling it. Community Java port: `io.modelcontextprotocol:sdk` (check Maven Central +for latest coordinates). + +**Do not** hand-roll JSON-RPC framing — the initialize/capability handshake has version +negotiation subtleties that the SDK handles correctly. + +**Estimated effort**: 3–4 days. + +### A3 — Team validation against `springbootdemo-tomcat11` + +Quick smoke-test script: +```bash +#!/bin/bash +# Initialize +echo '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"test","version":"1.0"}}}' \ + | java -jar axis2-mcp-bridge.jar --base-url http://localhost:8080/axis2-json-api + +# List tools +echo '{"jsonrpc":"2.0","id":2,"method":"tools/list","params":{}}' \ + | java -jar axis2-mcp-bridge.jar --base-url http://localhost:8080/axis2-json-api + +# Call a tool +echo '{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"processBigDataSet","arguments":{"datasetId":"mcp-test-001","datasetSize":1048576}}}' \ + | java -jar axis2-mcp-bridge.jar --base-url http://localhost:8080/axis2-json-api +``` + +**Estimated effort**: 1–2 days. + +### A4 — HTTP/SSE transport (post-demo, deferred) + +Adds persistent server mode (multiple Claude sessions sharing one bridge). Required for +production. Additive — no changes to Axis2 side or tool catalog format. + +``` +POST /mcp → JSON-RPC request +GET /mcp/sse → SSE stream for server-initiated messages +``` + +--- + +## Track B — Native MCP Transport (`axis2-transport-mcp`) + +**When**: After Track A is demonstrated. This is the Apache contribution — no other +Java framework has native MCP transport. + +**Module location**: `modules/transport-mcp/` + +**Interface**: Axis2's `TransportListener` + `TransportSender`. + +### Protocol translation + +``` +MCP tools/call (JSON-RPC 2.0) + ↓ +axis2-transport-mcp + ↓ +Axis2 MessageContext (service name + operation name + payload) + ↓ +Service implementation (same Java class as JSON-RPC and REST callers) + ↓ +Axis2 MessageContext (response payload) + ↓ +axis2-transport-mcp + ↓ +MCP tools/call result (JSON-RPC 2.0) +``` + +### Sequencing within Track B + +1. **stdio first** — simpler, no connection management, validates the + JSON-RPC 2.0 ↔ MessageContext translation layer end-to-end +2. **HTTP/SSE second** — reuses Axis2's existing HTTP infrastructure, adds + SSE for progress notifications on long-running service operations + +### Tool schema generation + +Populated from `axis2-openapi` Phase 2 output. `initialize` response includes +`capabilities.tools` derived from deployed services and their `@McpTool` annotations. + +### Starter integration + +```properties +axis2.transport.mcp.enabled=true +axis2.transport.mcp.transport=stdio # or http +axis2.transport.mcp.path=/mcp # only for http transport +``` + +### End state + +``` +Claude Desktop / AI agent → MCP (axis2-transport-mcp, native) + ↓ +REST clients → REST (@RestMapping, Phase 3) → Axis2 Service + ↑ (one Java class) +Existing JSON-RPC callers → JSON-RPC (unchanged) +``` + +--- + +## Key Design Decisions + +**Why stdio first for both tracks**: Simplest MCP transport, zero port conflicts, +works immediately with Claude Desktop and Cursor. Validates the translation layer before +adding HTTP connection management complexity. + +**Why OpenAPI as the bridge, not direct Axis2 introspection**: `/openapi-mcp.json` +decouples the bridge from Axis2 internals. The bridge works against any HTTP service +that serves this format — not just Axis2. This is useful for the Apache community +beyond the Axis2 user base. + +**Why not JAX-RS instead of `@RestMapping`**: JAX-RS brings a second framework +dependency and its own lifecycle. `@RestMapping` is a thin annotation processed by +Axis2's existing REST dispatcher — no container dependency, backwards compatible, +opt-in per-operation. + +**Why not Spring AI or LangChain4j as the MCP layer**: Those are application-layer +frameworks. The goal is transport-level integration so Axis2 services are callable from +*any* MCP client, not just Spring-based applications. `axis2-transport-mcp` is at the +right abstraction level. + +--- + +## Dependencies and Build + +Track A (`axis2-mcp-bridge`) requires: +- `axis2-openapi` module (for `/openapi-mcp.json`) +- MCP Java SDK (check coordinates at time of implementation) +- Java 21+ (HttpClient is standard library) +- No Axis2 core dependency — bridge is a separate process + +Track B (`axis2-transport-mcp`) requires: +- `axis2-core` / `axis2-kernel` (TransportListener interface) +- `axis2-openapi` (tool schema generation) +- MCP Java SDK (JSON-RPC 2.0 framing) + +Both tracks require `axis2-spring-boot-starter` (Phase 1) to wire transport config +via `application.properties`. + +--- + +## Next Immediate Actions + +1. **Start A1**: Add `McpToolCatalogServlet` to `modules/openapi/`. Start with + structural introspection (no annotation support yet) — get `/openapi-mcp.json` + serving a valid tool list from `springbootdemo-tomcat11`. + +2. **Check MCP Java SDK coordinates**: Verify artifact ID and version on Maven Central + before starting A2. The protocol is at `modelcontextprotocol.io/specification`. + +3. **Penguin demo (Track C, parallel)**: The Axis2/C financial benchmark service is + committed and compiles clean. When Penguin demo prep begins, the service is ready — + just needs `build_financial_service.sh` run on the Penguin host after Axis2/C install.
