back to all blogsSee all blog posts

Model Context Protocol Server 1.0 updates in 26.0.0.3-beta

image of author
Ismath Badsha on Mar 10, 2026
Post available in languages:

The 26.0.0.3-beta release updates the mcpServer-1.0 feature with response encoders and provides request ID access to tools for logging and auditing.

The Open Liberty 26.0.0.3-beta includes the following beta features (along with all GA features):

The Model Context Protocol (MCP) is an open standard that enables AI applications to access real-time information from external sources. The Liberty MCP Server feature (mcpServer-1.0) allows developers to expose the business logic of their applications, allowing it to be integrated into agentic AI workflows.

Encode responses with ContentEncoder and ToolResponseEncoder

When a client calls a tool, the object that is returned by the tool method is converted to a ToolResponse, which usually contains one or more Content objects. The ToolResponse maps directly to the result returned in the response.

If you need more control over the response from your tool, you can return a ToolResponse or Content object directly. Now, it is also possible to register encoders to control how other objects are converted into a response.

  • Use ToolResponseEncoder to convert an object into a ToolResponse, which gives you complete control over the whole response.

  • Use ContentEncoder when you only need to convert an object into a Content that is included in the response. You can also return a list of objects, and each object is individually converted into a Content and included in the response.

If a tool method returns an object for which no encoder is provided, JSON-B encodes the object as JSON, which is returned as text content.

Example

Consider a tool that does a search over some datastore:

@Tool(description = "search the data store")
public SearchResult search(@ToolArg(name="query", description="the query to run") String query) {
    SearchResult result = datastore.runQuery(query);
    return result;
}

In this scenario, the SearchResult object encapsulates a list of individual results. Each entry contains a summary, associated metadata, and a relevance score that indicates its relationship to the query.

By default, the SearchResult object that is returned is encoded as JSON by using JSON-B and placed into a TextContent. However, to return each search result summary as an individual TextContent and map the relevance score to a priority annotation, a ToolResponseEncoder is to be used.

Create a CDI bean that implements the ToolResponseEncoder interface and implement:

  • the encode method to create a ToolResponse from a SearchResult

  • the supports method to indicate that your encoder can be used for any SearchResult

@ApplicationScoped
public class SearchResultEncoder implements ToolResponseEncoder<SearchResult> {

    public boolean supports(Class<?> runtimeType) {
        // This encoder can encode SearchResult and any subtypes
        return SearchResult.class.isAssignableFrom(runtimeType);
    }

    public ToolResponse encode(SearchResult searchResult) {
        if (searchResult.results().isEmpty()) {
            return ToolResponse.error("No results");
        }

        ArrayList<TextContent> contents = new ArrayList<>();
        for (var result : searchResult.results()) {
            // Set the priority annotation based on the relevance
            Annotations annotations = new Annotations(null, null, result.relevance());
            // Create a TextContent from the summary, and add the annotations
            contents.add(new TextContent(result.summary(), null, annotations));
        }

        // Create a successful response, using the created TextContents
        return ToolResponse.success(contents);
    }
}

This encoder is used for any tools in the application that return a SearchResult

Access the request ID from a tool

Each request from an MCP client includes a unique session-based Request ID, which is now accessible to tools and is useful for logging and auditing.

To access the ID, add a RequestId parameter to the tool method:

@Tool(description = "search the data store")
public SearchResult search(@ToolArg(name="query") String query, RequestId requestId) {
    logger.log(INFO, "Running search (" + requestId.asString() + ") for query: " + query);
    // ....
}

Notable bug fixes

The following bugs have been fixed:

  • Output schemas were not generated correctly for asynchronous tool methods which have structuredContent = true

  • Omitting the arguments object when calling a tool would result in an error. The arguments object is optional if the tool does not require any arguments

Try it now

To try out these features, update your build tools to pull the Open Liberty All Beta Features package instead of the main release. To enable the MCP server feature, follow the instructions from MCP standalone blog. The beta works with Java SE 25, Java SE 21, Java SE 17, Java SE 11, and Java SE 8.

If you’re using Maven, you can install the All Beta Features package using:

<plugin>
    <groupId>io.openliberty.tools</groupId>
    <artifactId>liberty-maven-plugin</artifactId>
    <version>3.12.0</version>
    <configuration>
        <runtimeArtifact>
          <groupId>io.openliberty.beta</groupId>
          <artifactId>openliberty-runtime</artifactId>
          <version>26.0.0.3-beta</version>
          <type>zip</type>
        </runtimeArtifact>
    </configuration>
</plugin>

You must also add dependencies to your pom.xml file for the beta version of the APIs that are associated with the beta features that you want to try. For example, the following block adds dependencies for two example beta APIs:

<dependency>
    <groupId>org.example.spec</groupId>
    <artifactId>exampleApi</artifactId>
    <version>7.0</version>
    <type>pom</type>
    <scope>provided</scope>
</dependency>
<dependency>
    <groupId>example.platform</groupId>
    <artifactId>example.example-api</artifactId>
    <version>11.0.0</version>
    <scope>provided</scope>
</dependency>

Or for Gradle:

buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath 'io.openliberty.tools:liberty-gradle-plugin:3.10.0'
    }
}
apply plugin: 'liberty'
dependencies {
    libertyRuntime group: 'io.openliberty.beta', name: 'openliberty-runtime', version: '[26.0.0.3-beta,)'
}

Or if you’re using container images:

FROM icr.io/appcafe/open-liberty:beta

Or take a look at our Downloads page.

If you’re using IntelliJ IDEA, Visual Studio Code or Eclipse IDE, you can also take advantage of our open source Liberty developer tools to enable effective development, testing, debugging and application management all from within your IDE.

For more information on using a beta release, refer to the Installing Open Liberty beta releases documentation.

We welcome your feedback

Let us know what you think on our mailing list. If you hit a problem, post a question on StackOverflow. If you hit a bug, please raise an issue.