back to all blogsSee all blog posts

MCP Server updates in mcpServer-1.0 for Open Liberty 26.0.0.8-beta

image of author
Ismath Badsha on Jul 28, 2026
Post available in languages:

This beta release adds several new capabilities to mcpServer-1.0, including operational metrics for monitoring throughput and session lifecycle, and configurable server identity and metadata. The release also includes configurable session and async tool timeouts, support for custom Java types as default values in tool arguments, and full support for multi-WAR EAR deployments.

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

MCP Server metrics

The Model Context Protocol (MCP) is an open standard that enables AI applications to access real-time data and business logic from external sources. The Liberty MCP Server feature mcpServer-1.0 allows developers to expose their application’s tools and data for use in agentic AI workflows.

The MCP Server now exports operational metrics, making it possible to monitor operation throughput, duration, and session lifecycle by using Liberty’s existing observability stack. Metrics are available through JMX (monitor-1.0) and as OpenTelemetry histograms through mpTelemetry-2.0 or mpTelemetry-2.1.

Add monitor-1.0 alongside mcpServer-1.0 in your server.xml file. Optionally add mpTelemetry-2.0 (or 2.1) to export metrics to an OpenTelemetry collector:

<featureManager>
    <feature>mcpServer-1.0</feature>
    <feature>monitor-1.0</feature>
    <feature>mpTelemetry-2.0</feature>
</featureManager>

Two metrics are exported, following the OpenTelemetry semantic conventions for MCP:

mcp.server.operation.duration (Histogram, unit: seconds)

Tracks the duration of each MCP operation. A new data point is recorded per unique combination of the following attributes:

Attribute Description

mcp.method.name

Which MCP method was called, for example, tools/call, initialize, tools/list, ping. Present on every data point.

rpc.response.status_code

Whether the operation succeeded: ok on success, error on failure. Present on every data point.

jsonrpc.protocol.version

The JSON-RPC version used by the request, for example, 2.0. Present on every data point.

network.protocol.name

The HTTP protocol name, for example, http. Present on every data point.

network.protocol.version

The HTTP protocol version, for example, 1.1. Present on every data point.

network.transport

The transport layer. Always tcp.

mcp.protocol.version

The MCP protocol version that was negotiated with the client during initialize, for example, 2025-11-25. Present once initialization has occurred.

gen_ai.tool.name

The name of the tool that was called. Only present on tools/call data points.

error.type

Why the operation failed. Only present when rpc.response.status_code is error. Values include tool_error (the tool returned an error response), internal_error (an unexpected server exception), http_error (an HTTP-level failure), or a JSON-RPC error code such as INVALID_PARAMS.

mcp.server.session.duration (Histogram, unit: seconds)

Tracks the duration of each MCP session (stateful mode only). A new data point is recorded per unique combination of the following attributes:

Attribute Description

jsonrpc.protocol.version

The JSON-RPC version used when the session was created, for example, 2.0. Present on every data point.

mcp.protocol.version

The MCP protocol version negotiated during initialize, for example, 2025-11-25. Present on every data point.

network.protocol.name

The HTTP protocol name from when the session was created, for example, http. Present on every data point.

network.protocol.version

The HTTP protocol version from when the session was created, for example, 1.1. Present on every data point.

network.transport

The transport layer. Always tcp.

error.type

Why the session ended abnormally, for example, timeout. Only present when the session did not close cleanly.

Both metrics are also accessible through JMX using McpOperationStatsMXBean and McpSessionStatsMXBean, both of which expose Count, CountDetails, Duration, and DurationDetails. For more information, see the MicroProfile Telemetry documentation.

Configure MCP Server description and metadata

The MCP Server now sends a serverInfo block to clients during initialization, which MCP clients can display in their UI. Previously, this was hard-coded to a placeholder value. You can now configure the name, title, version, and description by using the <info> subelement within <mcpServer>:

<application location="my-app.war">
    <mcpServer>
        <info name="my-mcp-server"
              title="My MCP Server"
              version="2.5.0"
              description="Provides tools for querying customer data." />
    </mcpServer>
</application>

If the <info> subelement is not configured, the server defaults to name="mcp-server" and version="1.0.0".

Configure MCP session timeout and async tool timeout

Two previously hard-coded timeouts are now configurable through <mcpServer> attributes:

  • sessionTimeout — how long an inactive session is kept alive (default: 600s)

  • asyncTimeout — maximum execution time for an async tool call (default: 30s)

<application location="my-app.war">
    <mcpServer sessionTimeout="20m" asyncTimeout="60s"/>
</application>

Both attributes accept Liberty’s standard duration format (for example, 30s, 10m, 1h).

Custom types for default values in MCP tool arguments

The @ToolArg(defaultValue = "…​") annotation previously only worked with String, primitives, and enums. You can now handle any custom Java type by implementing DefaultValueConverter<T> as a CDI bean. Liberty automatically discovers and calls the converter when a default value string needs to be converted to your custom type.

import io.openliberty.mcp.annotations.DefaultValueConverter;
import jakarta.enterprise.context.ApplicationScoped;

@ApplicationScoped
public class DateRangeConverter implements DefaultValueConverter<DateRange> {
    @Override
    public DateRange convert(String defaultValue) {
        String[] parts = defaultValue.split("/");
        return new DateRange(LocalDate.parse(parts[0]), LocalDate.parse(parts[1]));
    }
}
@Tool(description = "Generate a report for a date range")
public String generateReport(
        @ToolArg(description = "Date range (YYYY-MM-DD/YYYY-MM-DD)",
                 defaultValue = "2024-01-01/2024-12-31")
        DateRange range) {
    return "Report from " + range.start + " to " + range.end;
}

If multiple converters exist for the same type, the one with the highest @jakarta.annotation.Priority value is called. Converters without @Priority default to priority 0.

Multi-module MCP applications

Liberty now fully supports deploying MCP applications as an EAR with multiple WAR modules. Each WAR module that contains MCP tools gets its own independent MCP server endpoint:

Tools that are declared in one WAR module are only available at that module’s endpoint — they are not visible to other modules. Liberty does not invoke ContentEncoder and ToolResponseEncoder beans from one module for requests to another module’s endpoint. Sessions and request tracking are isolated per module. Configure separate endpoints for each WAR module by using the moduleName attribute (the WAR file name within the EAR):

<application location="my-app.ear">
    <mcpServer path="/custom-mcp" moduleName="war1"/>
    <mcpServer path="/custom-mcp-for-war-2" moduleName="war2"/>
</application>

This creates two independent MCP endpoints:

  • http://localhost:9080/war1/custom-mcp

  • http://localhost:9080/war2/custom-mcp-for-war-2

Bug fixes

Canceling a tool call no longer logs an error

Previously, when a client cancelled a running tool call, the server incorrectly logged an ERROR for the expected OperationCancellationException. The client still receives the correct cancellation response, but the error is no longer logged.

@Priority on encoder CDI beans now resolved correctly

When sorting ContentEncoder or ToolResponseEncoder beans by @Priority, the priority was sometimes read from a CDI proxy rather than the actual bean class, causing non-deterministic ordering. The priority is now always resolved from the real bean class at CDI extension time.

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. Note that mcpServer-1.0 requires Java SE 17 or later.

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.1</version>
    <configuration>
        <runtimeArtifact>
          <groupId>io.openliberty.beta</groupId>
          <artifactId>openliberty-runtime</artifactId>
          <version>26.0.0.8-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:4.0.0'
    }
}
apply plugin: 'liberty'
dependencies {
    libertyRuntime group: 'io.openliberty.beta', name: 'openliberty-runtime', version: '[26.0.0.8-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.