Hibernate Validator Integration

The extension provides integration with Hibernate Validator, a Jakarta Validation implementation. First, it adds the quarkus-hibernate-validator dependency so that all @Tool methods with constraint annotations are validated when executed. The resulting constraint violations are transformed in a procotol error message. Additionaly, the extension adds a transitive dependency on com.github.victools:jsonschema-module-jakarta-validation which means that Jakarta Validation annotations will be considered when generating the input schema for @Tool methods.

If you want to use the Hibernate Validator integration in your application you’ll need to add the io.quarkiverse.mcp:quarkus-mcp-server-hibernate-validator extension to your build file first. For instance, with Maven, add the following dependency to your POM file:

<dependency>
    <groupId>io.quarkiverse.mcp</groupId>
    <artifactId>quarkus-mcp-server-hibernate-validator</artifactId>
    <version>${quarkus-mcp.version}</version>
</dependency>

Then you can use constraint annotations to define constraints for the tool arguments.

import io.quarkiverse.mcp.server.Tool;
import io.quarkiverse.mcp.server.ToolArg;
import jakarta.validation.constraints.NotBlank;

public class MyTools {

    @Tool(description = "Use this tool to foo!")
    String foo(@ToolArg(description = "The name") @NotBlank String name) { (1)
        return name.toUpperCase();
    }
}
1 @NotBlank defines a constraint used for the tool argument name.

When the tool method is executed and the name argument is blank, then the server responds with a tool response message like:

{
  "jsonrpc" : "2.0",
  "id" : 2,
  "result" : {
    "isError" : true,
    "content" : [ {
      "text" : "foo.name: must not be blank",
      "type" : "text"
    } ]
  }
}

Up to version 1.8.0 the server responded with a protocol error and JSON-RPC error code -32602 (invalid params):

{
  "jsonrpc" : "2.0",
  "id" : 3,
  "error" : {
    "code" : -32602,
    "message" : "foo.name: must not be blank"
  }
}

However, this behavior was not compliant with the specification. You can re-enable the previous behavior with quarkus.mcp.server.tools.input-validation-error=protocol.

Keep in mind that validation is only triggered if a method or any of its parameters declares a constraint annotation.

import io.quarkiverse.mcp.server.Tool;
import io.quarkiverse.mcp.server.ToolArg;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotBlank;

public class MyTools {

    @Tool(description = "Use this tool to foo!")
    String foo(@ToolArg(description = "The person") @Valid Person person) { (1)
        return person.name().toUpperCase();
    }

    public record Person(@NotBlank String name) {}
}
1 @Valid is required to trigger the validation of Person.

ConstraintViolationConverter

By default, a ConstraintViolationException is converted into:

  1. A ToolCallException for tools.

  2. An McpException with JSON-RPC error code -32602 (invalid params) for all other features.

The message contains ConstraintViolation#getPropertyPath() and ConstraintViolation#getMessage() for each violation.

However, it possible to implement a custom CDI bean that implements the io.quarkiverse.mcp.server.hibernate.validator.ConstraintViolationConverter interface and supply some custom logic.

import io.quarkiverse.mcp.server.hibernate.validator.ConstraintViolationConverter;
import io.quarkiverse.mcp.server.ToolCallException;
import jakarta.inject.Singleton;

@Singleton (1)
public MyConstraintViolationConverter implements ConstraintViolationConverter {

   @Override
   public Exception convert(ConstraintViolationException exception) {
      return new ToolCallException("Something went wrong!"); (2)
   }
}
1 Use the @Singleton scope to define a bean.
2 Turn the ConstraintViolationException into a business error with the specified message.