Skip to content

Commit 05358be

Browse files
committed
refactor: Remove ToolResult.text() helper method, update text content extraction to stream-based collection.
1 parent 22d3d9f commit 05358be

File tree

7 files changed

+74
-42
lines changed

7 files changed

+74
-42
lines changed

README.md

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,11 @@ Map<String, Object> args = Map.of(
173173
);
174174

175175
client.invokeTool("get-toy-price", args).thenAccept(result -> {
176-
System.out.println("Result: " + result.content().get(0).text());
176+
String output = result.content().stream()
177+
.filter(c -> "text".equals(c.type()) && c.text() != null)
178+
.map(c -> c.text())
179+
.collect(java.util.stream.Collectors.joining("\n"));
180+
System.out.println("Result:\n" + output);
177181
```
178182

179183
## Quickstart
@@ -194,7 +198,11 @@ public class App {
194198
// 2. Invoke a Tool
195199
client.invokeTool("get-toy-price", Map.of("description", "plush dinosaur"))
196200
.thenAccept(result -> {
197-
System.out.println("Tool Output: " + result.content().get(0).text());
201+
String output = result.content().stream()
202+
.filter(c -> "text".equals(c.type()) && c.text() != null)
203+
.map(c -> c.text())
204+
.collect(java.util.stream.Collectors.joining("\n"));
205+
System.out.println("Tool Output:\n" + output);
198206
})
199207
.exceptionally(ex -> {
200208
System.err.println("Error: " + ex.getMessage());
@@ -359,7 +367,11 @@ public class AuthExample {
359367
return tool.execute(Map.of("input", "some input"));
360368
})
361369
.thenAccept(result -> {
362-
System.out.println(result.content().get(0).text());
370+
String output = result.content().stream()
371+
.filter(c -> "text".equals(c.type()) && c.text() != null)
372+
.map(c -> c.text())
373+
.collect(java.util.stream.Collectors.joining("\n"));
374+
System.out.println(output);
363375
})
364376
.join();
365377
}

demo-applications/cymbal-transit/src/main/java/cloudcode/cymbal/web/CymbalTransitController.java

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,7 @@ public void init() {
189189
public CompletableFuture<String> findAllSchedules() {
190190
return mcpClient.invokeTool("find-bus-schedules", Collections.emptyMap()).thenApply(result -> {
191191
if (result.isError() || result.content() == null || result.content().isEmpty()) return "No schedules found.";
192-
return result.content().get(0).text();
192+
return getTextContent(result);
193193
});
194194
}
195195

@@ -201,7 +201,7 @@ public CompletableFuture<String> querySchedules(String origin, String destinatio
201201
return mcpClient.invokeTool("query-schedules", params).thenApply(result -> {
202202
if (result.isError() || result.content() == null || result.content().isEmpty()) return "No specific schedules found.";
203203
System.out.println(result);
204-
return result.content().get(0).text();
204+
return getTextContent(result);
205205
});
206206
}
207207

@@ -214,17 +214,26 @@ public CompletableFuture<String> bookTicket(String tripId, String passengerName)
214214
})
215215
.thenApply(result -> {
216216
if (result.isError() || result.content() == null || result.content().isEmpty()) return "Transaction failed.";
217-
return result.content().get(0).text();
217+
return getTextContent(result);
218218
});
219219
}
220220

221221
public CompletableFuture<String> searchPolicies(String searchQuery) {
222222
return mcpClient.invokeTool("search-policies", Map.of("search_query", searchQuery))
223223
.thenApply(result -> {
224224
if (result.isError() || result.content() == null || result.content().isEmpty()) return "No policy information found.";
225-
return result.content().get(0).text();
225+
return getTextContent(result);
226226
});
227227
}
228+
229+
private String getTextContent(com.google.cloud.mcp.ToolResult result) {
230+
if (result.content() == null)
231+
return "";
232+
return result.content().stream()
233+
.filter(c -> "text".equals(c.type()) && c.text() != null)
234+
.map(c -> c.text())
235+
.collect(java.util.stream.Collectors.joining("\n"));
236+
}
228237
}
229238

230239
/**

example/src/main/java/cloudcode/helloworld/ExampleUsage.java

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ public static void main(String[] args) {
101101
return client.invokeTool("get-retail-facet-filters", Map.of());
102102
})
103103
.thenCompose(result -> {
104-
System.out.println(" -> Result: " + (result.content() != null ? "Received Data" : "Empty"));
104+
System.out.println(" -> Result:\n" + getTextContent(result));
105105

106106
// STEP 3: INVOKE TOOL WITH AUTHENTICATED PARAMETERS
107107
System.out.println("\n[5] Testing Authenticated Tool: 'get-toy-price'...");
@@ -121,7 +121,7 @@ public static void main(String[] args) {
121121
return tool.execute(Map.of("description", "barbie"))
122122
.thenCompose(result1 -> {
123123
if (result1.content() != null && !result1.content().isEmpty()) {
124-
System.out.println(" -> Result (Unbound): " + result1.content().get(0).text());
124+
System.out.println(" -> Result (Unbound): " + result1.text());
125125
}
126126

127127
// NOW bind the parameter
@@ -136,9 +136,9 @@ public static void main(String[] args) {
136136
.thenAccept(result -> {
137137
System.out.println("\n[6] Final Result (Bound):");
138138
if (result.isError()) {
139-
System.err.println("Tool execution failed: " + result.content().get(0).text());
139+
System.err.println("Tool execution failed: " + getTextContent(result));
140140
} else if (result.content() != null && !result.content().isEmpty()) {
141-
String output = result.content().get(0).text();
141+
String output = getTextContent(result);
142142
System.out.println(" " + output.substring(0, Math.min(output.length(), 200)) + "...");
143143
} else {
144144
System.out.println(" Empty Response");
@@ -156,4 +156,13 @@ public static void main(String[] args) {
156156
}
157157
System.out.println("\n--- Test Suite Complete ---");
158158
}
159+
160+
private static String getTextContent(com.google.cloud.mcp.ToolResult result) {
161+
if (result.content() == null)
162+
return "";
163+
return result.content().stream()
164+
.filter(c -> "text".equals(c.type()) && c.text() != null)
165+
.map(c -> c.text())
166+
.collect(java.util.stream.Collectors.joining("\n"));
167+
}
159168
}

example/src/main/java/cloudcode/helloworld/InputValidationTest.java

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,8 @@ public static void main(String[] args) {
7070
try {
7171
Map<String, Object> validArgs = Map.of("description", "barbie");
7272
var result = tool.execute(validArgs).join();
73-
System.out.println(" ✅ Success! Output: " + (result.content().isEmpty() ? "Empty" : result.content().get(0).text()));
73+
System.out.println(
74+
" ✅ Success! Output: " + (result.content().isEmpty() ? "Empty" : getTextContent(result)));
7475
} catch (Exception e) {
7576
System.err.println(" ❌ Unexpected failure: " + e.getMessage());
7677
e.printStackTrace();
@@ -112,4 +113,13 @@ public static void main(String[] args) {
112113
}
113114
System.out.println("\n--- Done ---");
114115
}
116+
117+
private static String getTextContent(com.google.cloud.mcp.ToolResult result) {
118+
if (result.content() == null)
119+
return "";
120+
return result.content().stream()
121+
.filter(c -> "text".equals(c.type()) && c.text() != null)
122+
.map(c -> c.text())
123+
.collect(java.util.stream.Collectors.joining("\n"));
124+
}
115125
}

src/main/java/com/google/cloud/mcp/HttpMcpToolboxClient.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -245,9 +245,9 @@ public CompletableFuture<ToolResult> invokeTool(
245245
.POST(HttpRequest.BodyPublishers.ofString(requestBody));
246246

247247
if (reqAuth != null) {
248-
requestBuilder.header("Authorization", reqAuth);
248+
requestBuilder.setHeader("Authorization", reqAuth);
249249
}
250-
extraHeaders.forEach(requestBuilder::header);
250+
extraHeaders.forEach(requestBuilder::setHeader);
251251

252252
return httpClient
253253
.sendAsync(

src/main/java/com/google/cloud/mcp/ToolResult.java

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -38,21 +38,4 @@ public record ToolResult(
3838
@JsonIgnoreProperties(ignoreUnknown = true)
3939
public record Content(@JsonProperty("type") String type, @JsonProperty("text") String text) {}
4040

41-
/**
42-
* Helper method to retrieve all text content from the result as a single string stream.
43-
*
44-
* @return A single concatenated string of all text content.
45-
*/
46-
public String text() {
47-
if (content == null || content.isEmpty()) {
48-
return "";
49-
}
50-
StringBuilder sb = new StringBuilder();
51-
for (Content c : content) {
52-
if ("text".equals(c.type()) && c.text() != null) {
53-
sb.append(c.text()).append("\n");
54-
}
55-
}
56-
return sb.toString().trim();
57-
}
5841
}

src/test/java/com/google/cloud/mcp/e2e/McpToolboxClientTest.java

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -74,11 +74,11 @@ void testRunTool() {
7474
ToolResult result = tool.execute(Map.of("num_rows", "2")).join();
7575

7676
if (result.isError()) {
77-
System.out.println("ERROR OUTPUT: " + result.text());
77+
System.out.println("ERROR OUTPUT: " + getTextContent(result));
7878
}
7979

80-
assertFalse(result.isError(), "Expected successful result, but got error: " + result.text());
81-
String output = result.text();
80+
assertFalse(result.isError(), "Expected successful result, but got error: " + getTextContent(result));
81+
String output = getTextContent(result);
8282
assertTrue(output.contains("row1"), "Output didn't contain row1. Actual output: " + output);
8383
assertTrue(output.contains("row2"));
8484
assertFalse(output.contains("row3"));
@@ -92,7 +92,7 @@ void testBindParams() {
9292
Tool boundTool = tool.bindParam("num_rows", "3");
9393

9494
ToolResult result = boundTool.execute(Map.of()).join();
95-
String output = result.text();
95+
String output = getTextContent(result);
9696

9797
assertTrue(output.contains("row1"), "Actual output: " + output);
9898
assertTrue(output.contains("row2"));
@@ -106,7 +106,7 @@ void testBindParamsCallable() {
106106
Tool boundTool = tool.bindParam("num_rows", () -> "3");
107107

108108
ToolResult result = boundTool.execute(Map.of()).join();
109-
String output = result.text();
109+
String output = getTextContent(result);
110110

111111
assertTrue(output.contains("row1"), "Actual output: " + output);
112112
assertTrue(output.contains("row2"));
@@ -124,7 +124,7 @@ void testRunToolAuth() {
124124

125125
ToolResult result = tool.execute(Map.of("id", "2")).join();
126126
assertFalse(result.isError());
127-
String output = result.text();
127+
String output = getTextContent(result);
128128
assertTrue(output.contains("row2"));
129129
}
130130

@@ -136,9 +136,9 @@ void testRunToolWrongAuth() {
136136
"my-test-auth", () -> CompletableFuture.completedFuture(server.getAuthToken2()));
137137

138138
ToolResult result = tool.execute(Map.of("id", "2")).join();
139-
assertTrue(result.isError(), "Expected error for wrong auth. Actual output: " + result.text());
139+
assertTrue(result.isError(), "Expected error for wrong auth. Actual output: " + getTextContent(result));
140140
assertTrue(
141-
result.text().toLowerCase().contains("unauthorized"), "Actual output: " + result.text());
141+
getTextContent(result).toLowerCase().contains("unauthorized"), "Actual output: " + getTextContent(result));
142142
}
143143

144144
@Test
@@ -148,8 +148,8 @@ void testRunToolParamAuth() {
148148
"my-test-auth", () -> CompletableFuture.completedFuture(server.getAuthToken1()));
149149

150150
ToolResult result = tool.execute(Map.of()).join();
151-
assertFalse(result.isError(), "Expected success but got error: " + result.text());
152-
String output = result.text();
151+
assertFalse(result.isError(), "Expected success but got error: " + getTextContent(result));
152+
String output = getTextContent(result);
153153
assertTrue(output.contains("row4"), "Actual output: " + output);
154154
assertTrue(output.contains("row5"));
155155
assertTrue(output.contains("row6"));
@@ -163,6 +163,15 @@ void testRunToolParamAuthNoField() {
163163

164164
ToolResult result = tool.execute(Map.of()).join();
165165
assertTrue(result.isError());
166-
assertTrue(result.text().contains("no field named row_data"));
166+
assertTrue(getTextContent(result).contains("no field named row_data"));
167+
}
168+
169+
private String getTextContent(ToolResult result) {
170+
if (result.content() == null)
171+
return "";
172+
return result.content().stream()
173+
.filter(c -> "text".equals(c.type()) && c.text() != null)
174+
.map(c -> c.text())
175+
.collect(java.util.stream.Collectors.joining("\n"));
167176
}
168177
}

0 commit comments

Comments
 (0)