Package com.tnsai.spi

Interface McpClientFactory


public interface McpClientFactory
SPI for adapting an MCP server URL into a Healthcheckable probe. Lets tnsai-core's pre-flight validation pipeline run MCP initialize-handshake reachability checks without compile-time dependency on tnsai-mcp.

Why this SPI exists

The validation pipeline lives in tnsai-core; the only surface that knows how to perform an MCP initialize handshake lives in tnsai-mcp, which depends on tnsai-core — not the other way around. @MCPTool URLs are reachable from core via ActionMetadata.getMcpServerUrl(), but core has no protocol client to actually probe them. This SPI inverts the dependency: the tnsai-mcp module ships an implementation under META-INF/services/com.tnsai.spi.McpClientFactory, and MCPServerReachabilityValidator (AGENT-V011) discovers it via ServiceLoader.

Graceful degradation

When no McpClientFactory is on the classpath (e.g. the consumer hasn't pulled tnsai-mcp as a dependency), MCPServerReachabilityValidator stays silent — same shape as the Healthcheckable-marker guard used by V005 and V010. MCP-less consumers don't get spurious warnings; MCP-using consumers get pre-flight validation for free as soon as tnsai-mcp is on the runtime classpath.

Implementing


 package com.tnsai.mcp.spi;

 public final class DefaultMcpClientFactory implements McpClientFactory {
     @Override
     public Healthcheckable probeFor(String serverUrl, Map<String, Object> config) {
         return new McpHandshakeProbe(serverUrl, config);
     }
 }
 

Plus the service file at tnsai-mcp/src/main/resources/META-INF/services/com.tnsai.spi.McpClientFactory containing one line: com.tnsai.mcp.spi.DefaultMcpClientFactory.

The returned Healthcheckable adapter must follow the standard Healthcheckable contract — cheap, idempotent, in-budget, never throws.

Since:
0.8.5 (issue #237)
  • Method Details

    • probeFor

      Healthcheckable probeFor(String serverUrl, Map<String,Object> config)
      Build a Healthcheckable adapter for the given MCP server URL.
      Parameters:
      serverUrl - the MCP server URL declared on an @MCPTool(serverUrl = ...) action; non-null and non-blank
      config - additional per-server configuration (auth headers, custom timeouts, etc.); may be empty, never null. The shape of this map is intentionally open — implementations should document the keys they consume and ignore unknown keys.
      Returns:
      a non-null Healthcheckable that probes the server via the MCP initialize handshake. The returned probe must honour the timeout supplied to its own checkHealth(Duration) call and convert any failure to HealthStatus.unreachable(...) rather than throwing