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 5530655908e389a8e5a1aed59969d5bb0f695186
Author: Robert Lazarski <[email protected]>
AuthorDate: Sat Apr 11 11:48:37 2026 -1000

    Document MCP limitations: progress, stdio-only, auto-schema
    
    Adds "Known Limitations" section to mcp-architecture.md:
    
    - Progress notifications: blocked by bridge's blocking HTTP proxy
      architecture, not by stdio transport. Documents the three possible
      approaches (polling, streaming, callbacks) and notes that financial
      benchmarks complete within interactive time budgets (~1.4s for 100K
      Monte Carlo). Points to Axis2/C (2-3x faster) for latency-critical
      workloads with identical MCP tool schemas.
    
    - Stdio-only transport: HTTP/SSE (A4) deferred. Covers Claude Desktop,
      Cursor, and Claude Code use cases. Contributions welcome.
    
    - Auto-schema ServiceClass limitation: introspection requires explicit
      ServiceClass parameter. Spring-bean-only services need hand-written
      mcpInputSchema.
    
    Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
---
 .../apache/axis2/openapi/OpenApiSpecGenerator.java | 52 ++++++++++++++++-
 src/site/markdown/docs/mcp-architecture.md         | 67 ++++++++++++++++++++++
 2 files changed, 116 insertions(+), 3 deletions(-)

diff --git 
a/modules/openapi/src/main/java/org/apache/axis2/openapi/OpenApiSpecGenerator.java
 
b/modules/openapi/src/main/java/org/apache/axis2/openapi/OpenApiSpecGenerator.java
index 5c6fbc25ab..18d69ae815 100644
--- 
a/modules/openapi/src/main/java/org/apache/axis2/openapi/OpenApiSpecGenerator.java
+++ 
b/modules/openapi/src/main/java/org/apache/axis2/openapi/OpenApiSpecGenerator.java
@@ -604,11 +604,57 @@ public class OpenApiSpecGenerator {
      */
     private com.fasterxml.jackson.databind.node.ObjectNode 
generateSchemaFromServiceClass(
             AxisService service, String operationName) {
+        return generateSchemaFromServiceClass(service, operationName, null);
+    }
+
+    private com.fasterxml.jackson.databind.node.ObjectNode 
generateSchemaFromServiceClass(
+            AxisService service, String operationName, HttpServletRequest 
request) {
         try {
+            Class<?> serviceClass = null;
+
+            // Try 1: explicit ServiceClass parameter
             String className = getServiceClassName(service);
-            if (className == null) return null;
+            if (className != null) {
+                serviceClass = 
Thread.currentThread().getContextClassLoader().loadClass(className);
+            }
+
+            // Try 2: resolve Spring bean class from SpringBeanName via 
WebApplicationContext.
+            // Uses reflection to avoid a compile-time dependency on Spring 
Framework —
+            // the openapi module must work without Spring on the classpath.
+            // Mirrors the lookup in SpringServletContextObjectSupplier which 
uses
+            // 
WebApplicationContextUtils.getWebApplicationContext(servletContext).
+            if (serviceClass == null && request != null) {
+                try {
+                    String beanName = null;
+                    if (service.getParameter("SpringBeanName") != null) {
+                        beanName = (String) 
service.getParameter("SpringBeanName").getValue();
+                    }
+                    if (beanName != null) {
+                        jakarta.servlet.ServletContext sc = 
request.getServletContext();
+                        // Call 
WebApplicationContextUtils.getWebApplicationContext(sc) via reflection
+                        Class<?> wacUtils = Class.forName(
+                                
"org.springframework.web.context.support.WebApplicationContextUtils");
+                        java.lang.reflect.Method getWac = wacUtils.getMethod(
+                                "getWebApplicationContext", 
jakarta.servlet.ServletContext.class);
+                        Object ctx = getWac.invoke(null, sc);
+                        if (ctx != null) {
+                            java.lang.reflect.Method getBean = 
ctx.getClass().getMethod(
+                                    "getBean", String.class);
+                            Object bean = getBean.invoke(ctx, beanName);
+                            if (bean != null) {
+                                serviceClass = bean.getClass();
+                                log.debug("[MCP] Resolved Spring bean '" + 
beanName
+                                        + "' -> " + serviceClass.getName());
+                            }
+                        }
+                    }
+                } catch (Exception springEx) {
+                    log.debug("[MCP] Could not resolve Spring bean for "
+                            + service.getName() + ": " + 
springEx.getMessage());
+                }
+            }
 
-            Class<?> serviceClass = 
Thread.currentThread().getContextClassLoader().loadClass(className);
+            if (serviceClass == null) return null;
             java.lang.reflect.Method targetMethod = null;
             for (java.lang.reflect.Method m : serviceClass.getMethods()) {
                 if (m.getName().equals(operationName) && m.getParameterCount() 
== 1) {
@@ -938,7 +984,7 @@ public class OpenApiSpecGenerator {
                         // if introspection fails (e.g., no ServiceClass 
parameter,
                         // method not found, or primitive parameters).
                         com.fasterxml.jackson.databind.node.ObjectNode schema =
-                                generateSchemaFromServiceClass(service, 
opName);
+                                generateSchemaFromServiceClass(service, 
opName, request);
                         if (schema != null) {
                             toolNode.set("inputSchema", schema);
                             log.debug("[MCP] Auto-generated inputSchema for "
diff --git a/src/site/markdown/docs/mcp-architecture.md 
b/src/site/markdown/docs/mcp-architecture.md
index d6ef60edd0..f460aa0463 100644
--- a/src/site/markdown/docs/mcp-architecture.md
+++ b/src/site/markdown/docs/mcp-architecture.md
@@ -360,6 +360,73 @@ MCP and OpenAPI support needs validation across the full 
container/JDK matrix:
 
 ---
 
+## Known Limitations
+
+### No progress notifications during long-running operations
+
+The MCP spec supports progress notifications — JSON-RPC messages sent from the
+server to the client while a tool call is executing. This is useful for
+operations like Monte Carlo simulations (100K+ paths can take 1-14 seconds)
+where the AI assistant could display incremental status.
+
+**The limitation is architectural, not transport-related.** The MCP stdio
+transport supports progress notifications natively (they are regular JSON-RPC
+notifications on stdout). The constraint is the bridge's HTTP proxy pattern:
+
+```
+Claude Desktop ←stdio→ axis2-mcp-bridge ←blocking HTTP POST→ Axis2 service
+```
+
+The bridge sends one HTTP POST to Axis2 and blocks until the full response
+arrives. During a long computation, the bridge has no way to obtain 
intermediate
+status from the service. Adding progress support would require one of:
+
+- A polling side-channel (bridge polls a status endpoint while the main call 
runs)
+- HTTP chunked/streaming responses from Axis2
+- A callback mechanism from the service to the bridge
+
+These are non-trivial changes to the Axis2 response pipeline and the bridge
+architecture.
+
+**Practical impact:** The financial benchmark services complete well within
+interactive time budgets — portfolio variance in under 1 ms, Monte Carlo
+100K paths in ~1.4 seconds on Java. For workloads where even this latency
+is a concern, the same financial benchmark operations are available on
+[Axis2/C](http://axis.apache.org/axis2/c/), which runs 2-3x faster:
+Monte Carlo 100K paths in ~0.7 seconds, 500-asset portfolio variance in
+232 μs vs Java's 660 μs (see [performance 
comparison](mcp-examples.md#full-performance-summary)).
+Both implementations expose identical MCP tool schemas — an AI assistant
+configured with either backend gets the same financial capabilities.
+
+### Stdio transport only (HTTP/SSE deferred)
+
+The MCP bridge currently supports stdio transport only (Claude Desktop
+subprocess model). HTTP/SSE transport (A4) — which would enable Claude
+API tool use, multi-user bridge sharing, and remote MCP clients — is
+deferred. Contributions welcome.
+
+### Auto-generated inputSchema from Java types
+
+When `mcpInputSchema` is not set in `services.xml`, the MCP catalog
+generator auto-generates a JSON Schema by introspecting the Java service
+method's parameter type. Two resolution strategies are used:
+
+1. **`ServiceClass` parameter** — the class is loaded directly from the
+   classpath. Works immediately on the first catalog request.
+2. **`SpringBeanName` parameter** — the bean is resolved from the Spring
+   `WebApplicationContext` via reflection (no compile-time Spring dependency
+   in the OpenAPI module). Works after Spring initialization is complete.
+
+Supported types: `int`/`long` → `integer`, `double`/`float` → `number`,
+`boolean` → `boolean`, `String` → `string`, arrays (including nested
+`double[][]`), `List<T>`, and POJOs → `object`.
+
+Explicit `mcpInputSchema` in `services.xml` always takes precedence —
+use it when you need `required` fields, `minimum`/`maximum` constraints,
+`default` values, or `description` text that reflection cannot provide.
+
+---
+
 ## Dependencies and Build
 
 Track A (`axis2-mcp-bridge`) requires:

Reply via email to