Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,11 @@

import com.fasterxml.jackson.annotation.JsonAlias;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.micrometer.common.util.StringUtils;
import io.modelcontextprotocol.client.McpAsyncClient;
import io.modelcontextprotocol.client.McpSyncClient;
import io.modelcontextprotocol.json.jackson.JacksonMcpJsonMapper;
import io.modelcontextprotocol.server.McpServerFeatures;
import io.modelcontextprotocol.server.McpStatelessServerFeatures;
import io.modelcontextprotocol.server.McpSyncServerExchange;
Expand Down Expand Up @@ -74,6 +76,8 @@ public final class McpToolUtils {
*/
public static final String TOOL_CONTEXT_MCP_EXCHANGE_KEY = "exchange";

private static final JacksonMcpJsonMapper objectMapper = new JacksonMcpJsonMapper(new ObjectMapper());

private McpToolUtils() {
}

Expand Down Expand Up @@ -253,6 +257,7 @@ private static SharedSyncToolSpecification toSharedSyncToolSpecification(ToolCal
.description(toolCallback.getToolDefinition().description())
.inputSchema(ModelOptionsUtils.jsonToObject(toolCallback.getToolDefinition().inputSchema(),
McpSchema.JsonSchema.class))
.outputSchema(objectMapper, toolCallback.getToolDefinition().outputSchema())
.build();

return new SharedSyncToolSpecification(tool, (exchangeOrContext, request) -> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@
* @author Thomas Vitale
* @since 1.0.0
*/
public record DefaultToolDefinition(String name, String description, String inputSchema) implements ToolDefinition {
public record DefaultToolDefinition(String name, String description, String inputSchema,
String outputSchema) implements ToolDefinition {

public DefaultToolDefinition {
Assert.hasText(name, "name cannot be null or empty");
Expand All @@ -46,6 +47,8 @@ public static final class Builder {

private String inputSchema;

private String outputSchema;

private Builder() {
}

Expand All @@ -64,12 +67,17 @@ public Builder inputSchema(String inputSchema) {
return this;
}

public Builder outputSchema(String outputSchema) {
this.outputSchema = outputSchema;
return this;
}

public ToolDefinition build() {
if (!StringUtils.hasText(this.description)) {
Assert.hasText(this.name, "toolName cannot be null or empty");
this.description = ParsingUtils.reConcatenateCamelCase(this.name, " ");
}
return new DefaultToolDefinition(this.name, this.description, this.inputSchema);
return new DefaultToolDefinition(this.name, this.description, this.inputSchema, this.outputSchema);
}

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ public interface ToolDefinition {
*/
String inputSchema();

String outputSchema();

/**
* Create a default {@link ToolDefinition} builder.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,10 @@ public static final class Builder<I, O> {

private Type inputType;

private String outputSchema;

private Type outputType;

private ToolMetadata toolMetadata;

private BiFunction<I, ToolContext, O> toolFunction;
Expand Down Expand Up @@ -206,6 +210,16 @@ public Builder<I, O> inputType(ParameterizedTypeReference<?> inputType) {
return this;
}

public Builder<I, O> outputSchema(String outputSchema) {
this.outputSchema = outputSchema;
return this;
}

public Builder<I, O> outputType(Type outputType) {
this.outputType = outputType;
return this;
}

public Builder<I, O> toolMetadata(ToolMetadata toolMetadata) {
this.toolMetadata = toolMetadata;
return this;
Expand All @@ -224,6 +238,8 @@ public FunctionToolCallback<I, O> build() {
: ToolUtils.getToolDescriptionFromName(this.name))
.inputSchema(StringUtils.hasText(this.inputSchema) ? this.inputSchema
: JsonSchemaGenerator.generateForType(this.inputType))
.outputSchema(StringUtils.hasText(this.outputSchema) ? this.outputSchema
: JsonSchemaGenerator.generateForType(this.outputType))
.build();
return new FunctionToolCallback<>(toolDefinition, this.toolMetadata, this.inputType, this.toolFunction,
this.toolCallResultConverter);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ class DefaultToolExecutionExceptionProcessorTests {
private final Error toolError = new Error("Error");

private final DefaultToolDefinition toolDefinition = new DefaultToolDefinition("toolName", "toolDescription",
"inputSchema");
"inputSchema", "outputSchema");

private final ToolExecutionException toolExecutionException = new ToolExecutionException(this.toolDefinition,
this.toolException);
Expand Down