|
| 1 | +--- |
| 2 | +layout: post |
| 3 | +title: "Model Context Protocol Server 1.0 updates in 26.0.0.3-beta" |
| 4 | +# Do NOT change the categories section |
| 5 | +categories: blog |
| 6 | +author_picture: https://avatars3.githubusercontent.com/IsmathBadsha |
| 7 | +author_github: https://github.com/IsmathBadsha |
| 8 | +seo-title: "Model Context Protocol Server 1.0 updates in 26.0.0.3-beta - OpenLiberty.io" |
| 9 | +seo-description: 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. |
| 10 | +blog_description: 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. |
| 11 | +open-graph-image: https://openliberty.io/img/twitter_card.jpg |
| 12 | +open-graph-image-alt: Open Liberty Logo |
| 13 | +--- |
| 14 | += Model Context Protocol Server 1.0 updates in 26.0.0.3-beta |
| 15 | +Ismath Badsha <https://github.com/IsmathBadsha> |
| 16 | +:imagesdir: / |
| 17 | +:url-prefix: |
| 18 | +:url-about: / |
| 19 | +//Blank line here is necessary before starting the body of the post. |
| 20 | + |
| 21 | +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. |
| 22 | + |
| 23 | +The link:{url-about}[Open Liberty] 26.0.0.3-beta includes the following beta features (along with link:{url-prefix}/docs/latest/reference/feature/feature-overview.html[all GA features]): |
| 24 | + |
| 25 | +* <<encoders, Encode responses with ContentEncoder and ToolResponseEncoder>> |
| 26 | +* <<requestid, Access the request ID from a tool>> |
| 27 | + |
| 28 | +See also link:{url-prefix}/blog/?search=beta&key=tag[previous Open Liberty beta blog posts]. |
| 29 | + |
| 30 | +// // // // DO NOT MODIFY THIS COMMENT BLOCK <GHA-BLOG-TOPIC> // // // // |
| 31 | +// Blog issue: https://github.com/OpenLiberty/open-liberty/issues/XXXXX |
| 32 | +// Contact/Reviewer: martindrozdz |
| 33 | +// // // // // // // // |
| 34 | +[#encoders] |
| 35 | +== Encode responses with ContentEncoder and ToolResponseEncoder |
| 36 | + |
| 37 | +The link:https://modelcontextprotocol.io/docs/getting-started/intro[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. |
| 38 | + |
| 39 | +When a client calls a tool, the object 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. |
| 40 | + |
| 41 | +If you need more control over the response from your tool, you can return a `ToolResponse` or `Content` object directly, but now it's also possible to register encoders to control how other objects are converted into a response. |
| 42 | + |
| 43 | +* Use `ToolResponseEncoder` to convert an object into a `ToolResponse`, which gives you complete control over the whole response. |
| 44 | +* Use `ContentEncoder` when you only need to convert an object into a `Content` that will be included in the response. This also allows you to return a list of objects, and each object will be individually converted into a `Content` and included in the response. |
| 45 | + |
| 46 | +If a tool method returns an object for which no encoder is provided, JSON-B is used to encode the object as JSON which is returned as text content. |
| 47 | + |
| 48 | +=== Example |
| 49 | + |
| 50 | +Say you have a tool which does a search over some datastore: |
| 51 | + |
| 52 | +[source,java] |
| 53 | +---- |
| 54 | +@Tool(description = "search the data store") |
| 55 | +public SearchResult search(@ToolArg(name="query", description="the query to run") String query) { |
| 56 | + SearchResult result = datastore.runQuery(query); |
| 57 | + return result; |
| 58 | +} |
| 59 | +---- |
| 60 | + |
| 61 | +Imagine that the `SearchResult` object includes a list of results which includes a summary, some metadata, and an indication of how relevant the result is to the query. |
| 62 | + |
| 63 | +By default, the returned `SearchResult` object will be encoded as JSON using JSON-B and the resulting JSON put into a `TextContent`. However, if instead we wanted each search result summary to be returned as its own `TextContent`, and set the priority annotation based on the relevance score, we can do that with a `ToolResponseEncoder`. |
| 64 | + |
| 65 | +Create a CDI bean which implements the `ToolResponseEncoder` interface and implement: |
| 66 | + |
| 67 | +* the `encode` method to create a `ToolResponse` from a `SearchResult` |
| 68 | +* the `supports` method to indicate that your encoder can be used for any `SearchResult`. |
| 69 | + |
| 70 | +[source,java] |
| 71 | +---- |
| 72 | +@ApplicationScoped |
| 73 | +public class SearchResultEncoder implements ToolResponseEncoder<SearchResult> { |
| 74 | +
|
| 75 | + public boolean supports(Class<?> runtimeType) { |
| 76 | + // This encoder can encode SearchResult and any subtypes |
| 77 | + return SearchResult.class.isAssignableFrom(runtimeType); |
| 78 | + } |
| 79 | +
|
| 80 | + public ToolResponse encode(SearchResult searchResult) { |
| 81 | + if (searchResult.results().isEmpty()) { |
| 82 | + return ToolResponse.error("No results"); |
| 83 | + } |
| 84 | +
|
| 85 | + ArrayList<TextContent> contents = new ArrayList<>(); |
| 86 | + for (var result : searchResult.results()) { |
| 87 | + // Set the priority annotation based on the relevance |
| 88 | + Annotations annotations = new Annotations(null, null, result.relevance()); |
| 89 | + // Create a TextContent from the summary, and add the annotations |
| 90 | + contents.add(new TextContent(result.summary(), null, annotations)); |
| 91 | + } |
| 92 | +
|
| 93 | + // Create a successful response, using the created TextContents |
| 94 | + return ToolResponse.success(contents); |
| 95 | + } |
| 96 | +} |
| 97 | +---- |
| 98 | + |
| 99 | +This encoder will be used for any tools in the application which return a `SearchResult`. |
| 100 | + |
| 101 | +// DO NOT MODIFY THIS LINE. </GHA-BLOG-TOPIC> |
| 102 | + |
| 103 | +// // // // DO NOT MODIFY THIS COMMENT BLOCK <GHA-BLOG-TOPIC> // // // // |
| 104 | +// Blog issue: https://github.com/OpenLiberty/open-liberty/issues/XXXXX |
| 105 | +// Contact/Reviewer: martindrozdz |
| 106 | +// // // // // // // // |
| 107 | +[#requestid] |
| 108 | +== Access the request ID from a tool |
| 109 | + |
| 110 | +Every request from an MCP client includes a Request ID which is unique to that session. Tools can now access that ID. This is mostly useful for logging or auditing. |
| 111 | + |
| 112 | +To access the ID, simply add a `RequestId` parameter to the tool method: |
| 113 | + |
| 114 | +[source,java] |
| 115 | +---- |
| 116 | +@Tool(description = "search the data store") |
| 117 | +public SearchResult search(@ToolArg(name="query") String query, RequestId requestId) { |
| 118 | + logger.log(INFO, "Running search (" + requestId.asString() + ") for query: " + query); |
| 119 | + // .... |
| 120 | +} |
| 121 | +---- |
| 122 | + |
| 123 | +// DO NOT MODIFY THIS LINE. </GHA-BLOG-TOPIC> |
| 124 | + |
| 125 | +=== Notable bug fixes |
| 126 | + |
| 127 | +The following bugs have been fixed: |
| 128 | + |
| 129 | +* Output schemas were not generated correctly for asynchronous tool methods which have `structuredContent = true` |
| 130 | +* 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. |
| 131 | + |
| 132 | +[#run] |
| 133 | +=== Try it now |
| 134 | + |
| 135 | +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 link:https://openliberty.io/blog/2025/10/23/mcp-standalone-blog.html[MCP standalone blog]. The beta works with Java SE 25, Java SE 21, Java SE 17, Java SE 11, and Java SE 8. |
| 136 | + |
| 137 | +If you're using link:{url-prefix}/guides/maven-intro.html[Maven], you can install the All Beta Features package using: |
| 138 | + |
| 139 | +[source,xml] |
| 140 | +---- |
| 141 | +<plugin> |
| 142 | + <groupId>io.openliberty.tools</groupId> |
| 143 | + <artifactId>liberty-maven-plugin</artifactId> |
| 144 | + <version>3.12.0</version> |
| 145 | + <configuration> |
| 146 | + <runtimeArtifact> |
| 147 | + <groupId>io.openliberty.beta</groupId> |
| 148 | + <artifactId>openliberty-runtime</artifactId> |
| 149 | + <version>26.0.0.3-beta</version> |
| 150 | + <type>zip</type> |
| 151 | + </runtimeArtifact> |
| 152 | + </configuration> |
| 153 | +</plugin> |
| 154 | +---- |
| 155 | + |
| 156 | +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: |
| 157 | + |
| 158 | +[source,xml] |
| 159 | +---- |
| 160 | +<dependency> |
| 161 | + <groupId>org.example.spec</groupId> |
| 162 | + <artifactId>exampleApi</artifactId> |
| 163 | + <version>7.0</version> |
| 164 | + <type>pom</type> |
| 165 | + <scope>provided</scope> |
| 166 | +</dependency> |
| 167 | +<dependency> |
| 168 | + <groupId>example.platform</groupId> |
| 169 | + <artifactId>example.example-api</artifactId> |
| 170 | + <version>11.0.0</version> |
| 171 | + <scope>provided</scope> |
| 172 | +</dependency> |
| 173 | +---- |
| 174 | + |
| 175 | +Or for link:{url-prefix}/guides/gradle-intro.html[Gradle]: |
| 176 | + |
| 177 | +[source,gradle] |
| 178 | +---- |
| 179 | +buildscript { |
| 180 | + repositories { |
| 181 | + mavenCentral() |
| 182 | + } |
| 183 | + dependencies { |
| 184 | + classpath 'io.openliberty.tools:liberty-gradle-plugin:3.10.0' |
| 185 | + } |
| 186 | +} |
| 187 | +apply plugin: 'liberty' |
| 188 | +dependencies { |
| 189 | + libertyRuntime group: 'io.openliberty.beta', name: 'openliberty-runtime', version: '[26.0.0.3-beta,)' |
| 190 | +} |
| 191 | +---- |
| 192 | + |
| 193 | +// // // // // // // // |
| 194 | +// In the preceding section: |
| 195 | +// Replace the Maven `3.12.0` with the latest version of the plugin: https://search.maven.org/artifact/io.openliberty.tools/liberty-maven-plugin |
| 196 | +// Replace the Gradle `3.10.0` with the latest version of the plugin: https://search.maven.org/artifact/io.openliberty.tools/liberty-gradle-plugin |
| 197 | +// TODO: Update GHA to automatically do the above. If the maven.org is problematic, then could fallback to using the GH Releases for the plugins |
| 198 | +// // // // // // // // |
| 199 | + |
| 200 | +Or if you're using link:{url-prefix}/docs/latest/container-images.html[container images]: |
| 201 | + |
| 202 | +[source] |
| 203 | +---- |
| 204 | +FROM icr.io/appcafe/open-liberty:beta |
| 205 | +---- |
| 206 | + |
| 207 | +Or take a look at our link:{url-prefix}/downloads/#runtime_betas[Downloads page]. |
| 208 | + |
| 209 | +If you're using link:https://plugins.jetbrains.com/plugin/14856-liberty-tools[IntelliJ IDEA], link:https://marketplace.visualstudio.com/items?itemName=Open-Liberty.liberty-dev-vscode-ext[Visual Studio Code] or link:https://marketplace.eclipse.org/content/liberty-tools[Eclipse IDE], you can also take advantage of our open source link:https://openliberty.io/docs/latest/develop-liberty-tools.html[Liberty developer tools] to enable effective development, testing, debugging and application management all from within your IDE. |
| 210 | + |
| 211 | +For more information on using a beta release, refer to the link:{url-prefix}docs/latest/installing-open-liberty-betas.html[Installing Open Liberty beta releases] documentation. |
| 212 | + |
| 213 | +[#feedback] |
| 214 | +== We welcome your feedback |
| 215 | + |
| 216 | +Let us know what you think on link:https://groups.io/g/openliberty[our mailing list]. If you hit a problem, link:https://stackoverflow.com/questions/tagged/open-liberty[post a question on StackOverflow]. If you hit a bug, link:https://github.com/OpenLiberty/open-liberty/issues[please raise an issue]. |
0 commit comments