Interface McpClientFactory
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 Summary
-
Method Details
-
probeFor
Build aHealthcheckableadapter for the given MCP server URL.- Parameters:
serverUrl- the MCP server URL declared on an@MCPTool(serverUrl = ...)action; non-null and non-blankconfig- additional per-server configuration (auth headers, custom timeouts, etc.); may be empty, nevernull. The shape of this map is intentionally open — implementations should document the keys they consume and ignore unknown keys.- Returns:
- a non-null
Healthcheckablethat probes the server via the MCPinitializehandshake. The returned probe must honour the timeout supplied to its owncheckHealth(Duration)call and convert any failure toHealthStatus.unreachable(...)rather than throwing
-