diff --git a/core/src/main/java/com/google/adk/tools/mcp/McpToolset.java b/core/src/main/java/com/google/adk/tools/mcp/McpToolset.java index 4cafb9681..dae35f77e 100644 --- a/core/src/main/java/com/google/adk/tools/mcp/McpToolset.java +++ b/core/src/main/java/com/google/adk/tools/mcp/McpToolset.java @@ -25,6 +25,7 @@ import com.google.adk.tools.BaseTool; import com.google.adk.tools.BaseToolset; import com.google.adk.tools.ToolPredicate; +import com.google.common.annotations.VisibleForTesting; import com.google.common.collect.ImmutableList; import com.google.common.primitives.Booleans; import io.modelcontextprotocol.client.McpSyncClient; @@ -416,10 +417,7 @@ public static McpToolset fromConfig(BaseTool.ToolConfig config, String configAbs } List toolNames = mcpToolsetConfig.toolFilter(); - Object connectionParameters = - Optional.ofNullable(mcpToolsetConfig.stdioConnectionParams()) - .or(() -> Optional.ofNullable(mcpToolsetConfig.sseServerParams())) - .orElse(mcpToolsetConfig.stdioConnectionParams()); + Object connectionParameters = resolveConnectionParameters(mcpToolsetConfig); // Create McpToolset with McpSessionManager having appropriate connection parameters if (toolNames != null) { @@ -431,4 +429,20 @@ public static McpToolset fromConfig(BaseTool.ToolConfig config, String configAbs throw new ConfigurationException("Failed to parse McpToolsetConfig from ToolArgsConfig", e); } } + + /** + * Resolves the single connection-parameters object from an already-validated config. {@code + * stdioServerParams} is converted to the MCP SDK {@link ServerParameters}, the type {@link + * DefaultMcpTransportBuilder} accepts; the other variants pass through unchanged. + */ + @VisibleForTesting + static Object resolveConnectionParameters(McpToolsetConfig mcpToolsetConfig) { + return Optional.ofNullable(mcpToolsetConfig.stdioConnectionParams()) + .or(() -> Optional.ofNullable(mcpToolsetConfig.sseServerParams())) + .or( + () -> + Optional.ofNullable(mcpToolsetConfig.stdioServerParams()) + .map(StdioServerParameters::toServerParameters)) + .orElseThrow(() -> new IllegalStateException("Validated MCP connection params missing.")); + } } diff --git a/core/src/test/java/com/google/adk/tools/mcp/McpToolsetTest.java b/core/src/test/java/com/google/adk/tools/mcp/McpToolsetTest.java index f00091d2d..164105aa6 100644 --- a/core/src/test/java/com/google/adk/tools/mcp/McpToolsetTest.java +++ b/core/src/test/java/com/google/adk/tools/mcp/McpToolsetTest.java @@ -31,6 +31,7 @@ import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import io.modelcontextprotocol.client.McpSyncClient; +import io.modelcontextprotocol.client.transport.ServerParameters; import io.modelcontextprotocol.json.McpJsonDefaults; import io.modelcontextprotocol.json.McpJsonMapper; import io.modelcontextprotocol.spec.McpSchema; @@ -369,4 +370,45 @@ public void getTools_succeedsOnLastRetryAttempt() { verify(mockMcpSessionManager, times(3)).createSession(); verify(mockMcpSyncClient, times(3)).listTools(); } + + @Test + public void resolveConnectionParameters_stdioServerParams_convertsToSdkServerParameters() { + McpToolsetConfig config = new McpToolsetConfig(); + config.setStdioServerParams(StdioServerParameters.builder().command("my-command").build()); + + Object resolved = McpToolset.resolveConnectionParameters(config); + + // Regression, Finding 1: this branch used to resolve to null (stdioServerParams was never + // consulted), deferring the failure to an NPE in DefaultMcpTransportBuilder.build(null). + assertThat(resolved).isInstanceOf(ServerParameters.class); + } + + @Test + public void resolveConnectionParameters_sseServerParams_passesThrough() { + McpToolsetConfig config = new McpToolsetConfig(); + SseServerParameters sseParams = + SseServerParameters.builder().url("http://localhost:8080").build(); + config.setSseServerParams(sseParams); + + assertThat(McpToolset.resolveConnectionParameters(config)).isSameInstanceAs(sseParams); + } + + @Test + public void resolveConnectionParameters_stdioConnectionParams_passesThrough() { + McpToolsetConfig config = new McpToolsetConfig(); + StdioConnectionParameters connectionParams = + StdioConnectionParameters.builder() + .serverParams(StdioServerParameters.builder().command("my-command").build()) + .build(); + config.setStdioConnectionParams(connectionParams); + + assertThat(McpToolset.resolveConnectionParameters(config)).isSameInstanceAs(connectionParams); + } + + @Test + public void resolveConnectionParameters_nothingSet_throwsIllegalStateException() { + assertThrows( + IllegalStateException.class, + () -> McpToolset.resolveConnectionParameters(new McpToolsetConfig())); + } }