Return Types Reference
Return Type Conversion
The Quarkus MCP Server automatically converts method return types to the appropriate MCP protocol types. This section explains the conversion rules for different feature types, eliminating the need to always return the exact protocol type.
Common Conversion Patterns
All MCP server features support the following common patterns:
-
Reactive types: Methods may return
io.smallrye.mutiny.Uni<T>wrapping any of the supported return types for asynchronous execution -
Automatic conversion: Non-native types are automatically encoded using the appropriate encoder API
-
Default encoders: Built-in JSON encoders are registered for common types
Tool Return Types
The result of a "tool call" operation is always represented as a ToolResponse.
However, @Tool methods can return other types that are automatically converted:
| Return Type | Conversion Result | Response Status |
|---|---|---|
|
Single |
Success |
|
Single content object (TextContent, ImageContent, etc.) |
Success |
|
List of content objects |
Success |
Any other type |
Encoded via |
Success |
|
Asynchronous execution, unwrapped and converted per rules above |
Success |
| A default content encoder is registered that encodes values as JSON. |
Example conversions:
import io.quarkiverse.mcp.server.Tool;
import io.quarkiverse.mcp.server.TextContent;
import io.quarkiverse.mcp.server.ToolResponse;
import io.smallrye.mutiny.Uni;
import java.util.List;
public class MyTools {
// Returns String - converted to TextContent
@Tool
String simple(String input) {
return "Processed: " + input;
}
// Returns Content - used directly
@Tool
TextContent withContent(String input) {
return new TextContent("Result: " + input);
}
// Returns List<String> - converted to List<TextContent>
@Tool
List<String> multiple(String input) {
return List.of("First: " + input, "Second: " + input);
}
// Returns custom type - encoded via ToolResponseEncoder
@Tool
MyResult custom(String input) {
return new MyResult(input, 42);
}
// Returns Uni - asynchronous conversion
@Tool
Uni<String> async(String input) {
return Uni.createFrom().item("Async result: " + input);
}
// Returns ToolResponse directly - no conversion
@Tool
ToolResponse explicit(String input) {
return ToolResponse.success(new TextContent("Explicit: " + input));
}
}
record MyResult(String text, int count) {
}
Prompt Return Types
The result of a "prompt get" operation is always represented as a PromptResponse.
However, @Prompt methods can return other types that are automatically converted:
| Return Type | Conversion Result |
|---|---|
|
Response with no description, single message |
|
Response with no description, list of messages |
Any other type |
Encoded via |
|
Asynchronous execution, unwrapped and converted per rules above |
Example conversions:
import io.quarkiverse.mcp.server.Prompt;
import io.quarkiverse.mcp.server.PromptMessage;
import io.quarkiverse.mcp.server.PromptResponse;
import io.quarkiverse.mcp.server.TextContent;
import io.smallrye.mutiny.Uni;
import java.util.List;
public class MyPrompts {
// Returns PromptMessage - converted to PromptResponse
@Prompt
PromptMessage simple(String topic) {
return PromptMessage.withUserRole(new TextContent("Tell me about " + topic));
}
// Returns List<PromptMessage> - converted to PromptResponse
@Prompt
List<PromptMessage> conversation(String topic) {
return List.of(
PromptMessage.withUserRole(new TextContent("Question about " + topic)),
PromptMessage.withAssistantRole(new TextContent("Here's information about " + topic))
);
}
// Returns Uni - asynchronous conversion
@Prompt
Uni<PromptMessage> async(String topic) {
return Uni.createFrom().item(
PromptMessage.withUserRole(new TextContent("Async prompt: " + topic))
);
}
// Returns PromptResponse directly - no conversion
@Prompt
PromptResponse explicit(String topic) {
return PromptResponse.withMessages(
PromptMessage.withUserRole(new TextContent("Explicit: " + topic))
);
}
}
Resource Return Types
The result of a "resource read" operation is always represented as a ResourceResponse.
However, @Resource and @ResourceTemplate methods can return other types that are automatically converted:
| Return Type | Conversion Result |
|---|---|
|
Response with single contents object (TextResourceContents, BlobResourceContents) |
|
Response with list of contents objects |
Any other type |
Encoded via |
|
Asynchronous execution, unwrapped and converted per rules above |
| A default resource contents encoder is registered that encodes values as JSON. |
Example conversions:
import io.quarkiverse.mcp.server.Resource;
import io.quarkiverse.mcp.server.ResourceTemplate;
import io.quarkiverse.mcp.server.TextResourceContents;
import io.quarkiverse.mcp.server.BlobResourceContents;
import io.quarkiverse.mcp.server.ResourceResponse;
import io.quarkiverse.mcp.server.RequestUri;
import io.smallrye.mutiny.Uni;
import java.util.List;
public class MyResources {
// Returns TextResourceContents - converted to ResourceResponse
@Resource(uri = "file:///data.txt")
TextResourceContents simple(RequestUri uri) {
return new TextResourceContents(uri.value(), "Resource content", "text/plain");
}
// Returns List<ResourceContents> - converted to ResourceResponse
@Resource(uri = "file:///multiple.txt")
List<TextResourceContents> multiple(RequestUri uri) {
return List.of(
new TextResourceContents(uri.value(), "Part 1", "text/plain"),
new TextResourceContents(uri.value(), "Part 2", "text/plain")
);
}
// Returns Uni - asynchronous conversion
@ResourceTemplate(uriTemplate = "file:///{path}")
Uni<TextResourceContents> async(String path, RequestUri uri) {
return Uni.createFrom().item(
new TextResourceContents(uri.value(), "Async content", "text/plain")
);
}
// Returns ResourceResponse directly - no conversion
@Resource(uri = "file:///explicit.txt")
ResourceResponse explicit(RequestUri uri) {
return new ResourceResponse(
List.of(new TextResourceContents(uri.value(), "Explicit", "text/plain"))
);
}
}
Completion Return Types
Completion methods for prompts and resource templates must return CompletionResponse.
However, @CompletePrompt and @CompleteResourceTemplate methods can return other types that are automatically converted:
| Return Type | Conversion Result |
|---|---|
|
Response with single value |
|
Response with list of values |
|
Asynchronous execution, unwrapped and converted per rules above |
Example conversions:
import io.quarkiverse.mcp.server.CompletePrompt;
import io.quarkiverse.mcp.server.CompleteResourceTemplate;
import io.quarkiverse.mcp.server.CompletionResponse;
import io.smallrye.mutiny.Uni;
import java.util.List;
public class MyCompletions {
// Returns String - converted to CompletionResponse with single value
@CompletePrompt("myPrompt")
String singleValue(String partial) {
return "matched-value";
}
// Returns List<String> - converted to CompletionResponse with values
@CompletePrompt("myPrompt")
List<String> multipleValues(String partial) {
return List.of("option1", "option2", "option3");
}
// Returns Uni - asynchronous conversion
@CompleteResourceTemplate("myTemplate")
Uni<List<String>> async(String partial) {
return Uni.createFrom().item(List.of("async1", "async2"));
}
// Returns CompletionResponse directly - no conversion
@CompletePrompt("myPrompt")
CompletionResponse explicit(String partial) {
return CompletionResponse.create(List.of("explicit1", "explicit2"));
}
}
Custom Encoders
When returning custom types, you can provide custom encoders to control the conversion process. See the main documentation for details on implementing:
-
ToolResponseEncoderfor tool return types -
ContentEncoderfor content encoding -
PromptResponseEncoderfor prompt return types -
ResourceContentsEncoderfor resource return types
This allows you to return domain objects directly from your methods while controlling how they are serialized for MCP clients.