Skip to content

Commit 22a6d84

Browse files
google-genai-botcopybara-github
authored andcommitted
feat: add ExampleTool to ComponentRegistry
PiperOrigin-RevId: 846220473
1 parent 464f0b2 commit 22a6d84

File tree

5 files changed

+129
-27
lines changed

5 files changed

+129
-27
lines changed

core/src/main/java/com/google/adk/tools/mcp/McpSessionManager.java

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,14 +61,19 @@ public static McpSyncClient initializeSession(
6161
Object connectionParams, McpTransportBuilder transportBuilder) {
6262
Duration initializationTimeout = null;
6363
Duration requestTimeout = null;
64-
McpClientTransport transport = transportBuilder.build(connectionParams);
65-
if (connectionParams instanceof SseServerParameters sseServerParams) {
64+
Object transportBuilderParams = connectionParams;
65+
if (connectionParams instanceof StdioConnectionParameters stdioConnectionParameters) {
66+
transportBuilderParams = stdioConnectionParameters.serverParams().toServerParameters();
67+
requestTimeout = stdioConnectionParameters.timeoutDuration();
68+
} else if (connectionParams instanceof SseServerParameters sseServerParams) {
6669
initializationTimeout = sseServerParams.timeout();
6770
requestTimeout = sseServerParams.sseReadTimeout();
6871
} else if (connectionParams instanceof StreamableHttpServerParameters streamableParams) {
6972
initializationTimeout = streamableParams.timeout();
7073
requestTimeout = streamableParams.readTimeout();
7174
}
75+
McpClientTransport transport = transportBuilder.build(transportBuilderParams);
76+
7277
McpSyncClient client =
7378
McpClient.sync(transport)
7479
.initializationTimeout(

core/src/main/java/com/google/adk/tools/mcp/McpToolset.java

Lines changed: 28 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import com.google.adk.agents.ReadonlyContext;
2525
import com.google.adk.tools.BaseTool;
2626
import com.google.adk.tools.BaseToolset;
27+
import com.google.common.primitives.Booleans;
2728
import io.modelcontextprotocol.client.McpSyncClient;
2829
import io.modelcontextprotocol.client.transport.ServerParameters;
2930
import io.modelcontextprotocol.spec.McpSchema.ListToolsResult;
@@ -285,12 +286,23 @@ public void close() {
285286

286287
/** Configuration class for MCPToolset. */
287288
public static class McpToolsetConfig extends JsonBaseModel {
289+
290+
private StdioConnectionParameters stdioConnectionParams;
291+
288292
private StdioServerParameters stdioServerParams;
289293

290294
private SseServerParameters sseServerParams;
291295

292296
private List<String> toolFilter;
293297

298+
public StdioConnectionParameters stdioConnectionParams() {
299+
return stdioConnectionParams;
300+
}
301+
302+
public void setStdioConnectionParams(StdioConnectionParameters stdioConnectionParams) {
303+
this.stdioConnectionParams = stdioConnectionParams;
304+
}
305+
294306
public StdioServerParameters stdioServerParams() {
295307
return stdioServerParams;
296308
}
@@ -337,23 +349,26 @@ public static McpToolset fromConfig(BaseTool.ToolConfig config, String configAbs
337349
mapper.convertValue(config.args(), McpToolsetConfig.class);
338350

339351
// Validate that exactly one parameter type is set
340-
if ((mcpToolsetConfig.stdioServerParams() != null)
341-
== (mcpToolsetConfig.sseServerParams() != null)) {
352+
if (Booleans.countTrue(
353+
mcpToolsetConfig.stdioServerParams() != null,
354+
mcpToolsetConfig.sseServerParams() != null,
355+
mcpToolsetConfig.stdioConnectionParams() != null)
356+
!= 1) {
342357
throw new ConfigurationException(
343-
"Exactly one of stdioServerParams or sseServerParams must be set for McpToolset");
358+
"Exactly one of stdioConnectionParams, stdioServerParams or sseServerParams must be set"
359+
+ " for McpToolset");
344360
}
345361

346362
// Convert tool filter to Optional<Object>
347-
Optional<Object> toolFilter =
348-
Optional.ofNullable(mcpToolsetConfig.toolFilter()).map(filter -> filter);
349-
350-
// Create McpToolset with appropriate connection parameters
351-
if (mcpToolsetConfig.stdioServerParams() != null) {
352-
return new McpToolset(
353-
mcpToolsetConfig.stdioServerParams().toServerParameters(), mapper, toolFilter);
354-
} else {
355-
return new McpToolset(mcpToolsetConfig.sseServerParams(), mapper, toolFilter);
356-
}
363+
Optional<Object> toolFilter = Optional.ofNullable(mcpToolsetConfig.toolFilter());
364+
365+
Object connectionParameters =
366+
Optional.<Object>ofNullable(mcpToolsetConfig.stdioConnectionParams())
367+
.or(() -> Optional.ofNullable(mcpToolsetConfig.sseServerParams()))
368+
.orElse(mcpToolsetConfig.stdioConnectionParams());
369+
370+
// Create McpToolset with McpSessionManager having appropriate connection parameters
371+
return new McpToolset(new McpSessionManager(connectionParameters), mapper, toolFilter);
357372
} catch (IllegalArgumentException e) {
358373
throw new ConfigurationException("Failed to parse McpToolsetConfig from ToolArgsConfig", e);
359374
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
package com.google.adk.tools.mcp;
2+
3+
import com.fasterxml.jackson.annotation.JsonCreator;
4+
import com.fasterxml.jackson.annotation.JsonIgnore;
5+
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
6+
import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder;
7+
import com.google.auto.value.AutoValue;
8+
import java.time.Duration;
9+
10+
@AutoValue
11+
@JsonDeserialize(builder = StdioConnectionParameters.Builder.class)
12+
public abstract class StdioConnectionParameters {
13+
14+
private static final long MILLIS_IN_SEC = 1000L;
15+
private static final float DEFAULT_TIMEOUT_SECS = 5f;
16+
17+
StdioConnectionParameters() {}
18+
19+
public abstract StdioServerParameters serverParams();
20+
21+
// Timeout in seconds
22+
public abstract float timeout();
23+
24+
@JsonIgnore
25+
public Duration timeoutDuration() {
26+
return Duration.ofMillis((long) (timeout() * MILLIS_IN_SEC));
27+
}
28+
29+
@AutoValue.Builder
30+
@JsonPOJOBuilder(buildMethodName = "build", withPrefix = "")
31+
public abstract static class Builder {
32+
33+
@JsonCreator
34+
public static Builder jacksonBuilder() {
35+
return StdioConnectionParameters.builder();
36+
}
37+
38+
public abstract Builder serverParams(StdioServerParameters serverParams);
39+
40+
public abstract Builder timeout(float timeout);
41+
42+
public abstract StdioConnectionParameters build();
43+
}
44+
45+
public static Builder builder() {
46+
Builder b = new AutoValue_StdioConnectionParameters.Builder();
47+
return b.timeout(DEFAULT_TIMEOUT_SECS);
48+
}
49+
}

core/src/main/java/com/google/adk/utils/ComponentRegistry.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import com.google.adk.tools.AgentTool;
3030
import com.google.adk.tools.BaseTool;
3131
import com.google.adk.tools.BaseToolset;
32+
import com.google.adk.tools.ExampleTool;
3233
import com.google.adk.tools.ExitLoopTool;
3334
import com.google.adk.tools.GoogleMapsTool;
3435
import com.google.adk.tools.GoogleSearchTool;
@@ -115,6 +116,7 @@ private void initializePreWiredEntries() {
115116

116117
registerAdkToolClass(AgentTool.class);
117118
registerAdkToolClass(LongRunningFunctionTool.class);
119+
registerAdkToolClass(ExampleTool.class);
118120

119121
registerAdkToolsetClass(McpToolset.class);
120122
// TODO: add all python tools that also exist in Java.

core/src/test/java/com/google/adk/tools/mcp/McpToolsetTest.java

Lines changed: 43 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,12 @@ public class McpToolsetTest {
5353

5454
private static final McpJsonMapper jsonMapper = McpJsonMapper.getDefault();
5555

56+
private static final ImmutableMap<String, Object> STDIO_SERVER_PARAMS =
57+
ImmutableMap.of(
58+
"command", "test-command",
59+
"args", ImmutableList.of("arg1", "arg2"),
60+
"env", ImmutableMap.of("KEY1", "value1"));
61+
5662
@Test
5763
public void testMcpToolsetConfig_withStdioServerParams_parsesCorrectly() {
5864
McpToolsetConfig mcpConfig = new McpToolsetConfig();
@@ -120,9 +126,25 @@ public void testFromConfig_bothStdioAndSseParams_throwsConfigurationException()
120126
ConfigurationException exception =
121127
assertThrows(ConfigurationException.class, () -> McpToolset.fromConfig(config, configPath));
122128

123-
assertThat(exception)
124-
.hasMessageThat()
125-
.contains("Exactly one of stdioServerParams or sseServerParams must be set");
129+
assertThat(exception).hasMessageThat().containsMatch("Exactly one of .* must be set");
130+
}
131+
132+
@Test
133+
public void testFromConfig_bothStdioConnectionParamsAndSseParams_throwsConfigurationException() {
134+
BaseTool.ToolArgsConfig args = new BaseTool.ToolArgsConfig();
135+
args.put(
136+
"stdioConnectionParams",
137+
ImmutableMap.of(
138+
"serverParams",
139+
ImmutableMap.of("command", "test-command", "args", ImmutableList.of("arg1", "arg2"))));
140+
args.put("sseServerParams", ImmutableMap.of("url", "http://localhost:8080"));
141+
BaseTool.ToolConfig config = new BaseTool.ToolConfig("mcp_toolset", args);
142+
String configPath = "/path/to/config.yaml";
143+
144+
ConfigurationException exception =
145+
assertThrows(ConfigurationException.class, () -> McpToolset.fromConfig(config, configPath));
146+
147+
assertThat(exception).hasMessageThat().containsMatch("Exactly one of .* must be set");
126148
}
127149

128150
@Test
@@ -135,20 +157,13 @@ public void testFromConfig_neitherStdioNorSseParams_throwsConfigurationException
135157
ConfigurationException exception =
136158
assertThrows(ConfigurationException.class, () -> McpToolset.fromConfig(config, configPath));
137159

138-
assertThat(exception)
139-
.hasMessageThat()
140-
.contains("Exactly one of stdioServerParams or sseServerParams must be set");
160+
assertThat(exception).hasMessageThat().containsMatch("Exactly one of .* must be set");
141161
}
142162

143163
@Test
144164
public void testFromConfig_validStdioParams_createsToolset() throws ConfigurationException {
145165
BaseTool.ToolArgsConfig args = new BaseTool.ToolArgsConfig();
146-
args.put(
147-
"stdioServerParams",
148-
ImmutableMap.of(
149-
"command", "test-command",
150-
"args", ImmutableList.of("arg1", "arg2"),
151-
"env", ImmutableMap.of("KEY1", "value1")));
166+
args.put("stdioServerParams", STDIO_SERVER_PARAMS);
152167
args.put("toolFilter", ImmutableList.of("tool1", "tool2"));
153168

154169
BaseTool.ToolConfig config = new BaseTool.ToolConfig("mcp_toolset", args);
@@ -179,6 +194,22 @@ public void testFromConfig_validSseParams_createsToolset() throws ConfigurationE
179194
// The toolset should be created successfully with SSE parameters
180195
}
181196

197+
@Test
198+
public void testFromConfig_validStdioConnectionParams_createsToolset()
199+
throws ConfigurationException {
200+
BaseTool.ToolArgsConfig args = new BaseTool.ToolArgsConfig();
201+
args.put(
202+
"stdioConnectionParams",
203+
ImmutableMap.of("timeout", 10f, "serverParams", STDIO_SERVER_PARAMS));
204+
205+
BaseTool.ToolConfig config = new BaseTool.ToolConfig("mcp_toolset", args);
206+
String configPath = "/path/to/config.yaml";
207+
208+
McpToolset toolset = McpToolset.fromConfig(config, configPath);
209+
210+
assertThat(toolset).isNotNull();
211+
}
212+
182213
@Test
183214
public void testFromConfig_onlySseParams_doesNotUseStdioBranch() throws ConfigurationException {
184215
// This test ensures that when only SSE params are provided, the SSE branch is taken

0 commit comments

Comments
 (0)