feat(java): Update the Java SDK to 0.8.0 (#190)
* feat(java): Update the Java SDK to 0.8.0 - Update Java SDK version from 0.7.0 to 0.8.0 - Refactor transport layer to use transportProvider pattern - Rename registrations to specifications in server API - Add exchange parameter to callback functions - Add breaking changes note - Enhance MCP Java SDK documentation with sampling * Add documentation for sampling capabilities in MCP Server * Expand documentation for Tool, Resource, and Prompt specifications * Add Spring AI integration to the client/server docs Signed-off-by: Christian Tzolov <christian.tzolov@broadcom.com> * refactor(java-sdk): improve API usage example - Replace Content builder pattern with direct TextContent constructor - Replace ModelHint builder pattern with static factory method Signed-off-by: Christian Tzolov <christian.tzolov@broadcom.com> --------- Signed-off-by: Christian Tzolov <christian.tzolov@broadcom.com>
This commit is contained in:
parent
b81c31f775
commit
6e1bbc4e30
1 changed files with 226 additions and 48 deletions
|
|
@ -3,6 +3,12 @@ title: MCP Server
|
|||
description: Learn how to implement and configure a Model Context Protocol (MCP) server
|
||||
---
|
||||
|
||||
<Note>
|
||||
### Breaking Changes in 0.8.0 ⚠️
|
||||
**Note:** Version 0.8.0 introduces several breaking changes including a new session-based architecture.
|
||||
If you're upgrading from 0.7.0, please refer to the [Migration Guide](https://github.com/modelcontextprotocol/java-sdk/blob/main/migration-0.8.0.md) for detailed instructions.
|
||||
</Note>
|
||||
|
||||
## Overview
|
||||
|
||||
The MCP Server is a foundational component in the Model Context Protocol (MCP) architecture that provides tools, resources, and capabilities to clients. It implements the server-side of the protocol, responsible for:
|
||||
|
|
@ -15,13 +21,18 @@ The MCP Server is a foundational component in the Model Context Protocol (MCP) a
|
|||
- Managing concurrent client connections
|
||||
- Providing structured logging and notifications
|
||||
|
||||
<Tip>
|
||||
The [Spring-AI MCP Server](https://docs.spring.io/spring-ai/reference/api/mcp/mcp-server-boot-starter-docs.html) integration extends the MCP Java SDK to
|
||||
provide auto-configuration for MCP servdr functionality in Spring Boot applications.
|
||||
</Tip>
|
||||
|
||||
The server supports both synchronous and asynchronous APIs, allowing for flexible integration in different application contexts.
|
||||
|
||||
<Tabs>
|
||||
<Tab title="Sync API">
|
||||
```java
|
||||
// Create a server with custom configuration
|
||||
McpSyncServer syncServer = McpServer.sync(transport)
|
||||
McpSyncServer syncServer = McpServer.sync(transportProvider)
|
||||
.serverInfo("my-server", "1.0.0")
|
||||
.capabilities(ServerCapabilities.builder()
|
||||
.resources(true) // Enable resource support
|
||||
|
|
@ -32,9 +43,9 @@ McpSyncServer syncServer = McpServer.sync(transport)
|
|||
.build();
|
||||
|
||||
// Register tools, resources, and prompts
|
||||
syncServer.addTool(syncToolRegistration);
|
||||
syncServer.addResource(syncResourceRegistration);
|
||||
syncServer.addPrompt(syncPromptRegistration);
|
||||
syncServer.addTool(syncToolSpecification);
|
||||
syncServer.addResource(syncResourceSpecification);
|
||||
syncServer.addPrompt(syncPromptSpecification);
|
||||
|
||||
// Send logging notifications
|
||||
syncServer.loggingNotification(LoggingMessageNotification.builder()
|
||||
|
|
@ -51,7 +62,7 @@ syncServer.close();
|
|||
<Tab title="Async API">
|
||||
```java
|
||||
// Create an async server with custom configuration
|
||||
McpAsyncServer asyncServer = McpServer.async(transport)
|
||||
McpAsyncServer asyncServer = McpServer.async(transportProvider)
|
||||
.serverInfo("my-server", "1.0.0")
|
||||
.capabilities(ServerCapabilities.builder()
|
||||
.resources(true) // Enable resource support
|
||||
|
|
@ -62,15 +73,15 @@ McpAsyncServer asyncServer = McpServer.async(transport)
|
|||
.build();
|
||||
|
||||
// Register tools, resources, and prompts
|
||||
asyncServer.addTool(asyncToolRegistration)
|
||||
asyncServer.addTool(asyncToolSpecification)
|
||||
.doOnSuccess(v -> logger.info("Tool registered"))
|
||||
.subscribe();
|
||||
|
||||
asyncServer.addResource(asyncResourceRegistration)
|
||||
asyncServer.addResource(asyncResourceSpecification)
|
||||
.doOnSuccess(v -> logger.info("Resource registered"))
|
||||
.subscribe();
|
||||
|
||||
asyncServer.addPrompt(asyncPromptRegistration)
|
||||
asyncServer.addPrompt(asyncPromptSpecification)
|
||||
.doOnSuccess(v -> logger.info("Prompt registered"))
|
||||
.subscribe();
|
||||
|
||||
|
|
@ -90,9 +101,11 @@ asyncServer.close()
|
|||
</Tabs>
|
||||
|
||||
|
||||
## Server Transport
|
||||
## Server Transport Providers
|
||||
|
||||
The transport layer in the MCP SDK is responsible for handling the communication between clients and servers. It provides different implementations to support various communication protocols and patterns. The SDK includes several built-in transport implementations:
|
||||
The transport layer in the MCP SDK is responsible for handling the communication between clients and servers.
|
||||
It provides different implementations to support various communication protocols and patterns.
|
||||
The SDK includes several built-in transport provider implementations:
|
||||
|
||||
<Tabs>
|
||||
|
||||
|
|
@ -101,7 +114,7 @@ The transport layer in the MCP SDK is responsible for handling the communication
|
|||
Create in-process based transport:
|
||||
|
||||
```java
|
||||
StdioServerTransport transport = new StdioServerTransport(new ObjectMapper());
|
||||
StdioServerTransportProvider transportProvider = new StdioServerTransportProvider(new ObjectMapper());
|
||||
```
|
||||
|
||||
Provides bidirectional JSON-RPC message handling over standard input/output streams with non-blocking message processing, serialization/deserialization, and graceful shutdown support.
|
||||
|
|
@ -124,13 +137,13 @@ The transport layer in the MCP SDK is responsible for handling the communication
|
|||
@Configuration
|
||||
class McpConfig {
|
||||
@Bean
|
||||
WebFluxSseServerTransport webFluxSseServerTransport(ObjectMapper mapper) {
|
||||
return new WebFluxSseServerTransport(mapper, "/mcp/message");
|
||||
WebFluxSseServerTransportProvider webFluxSseServerTransportProvider(ObjectMapper mapper) {
|
||||
return new WebFluxSseServerTransportProvider(mapper, "/mcp/message");
|
||||
}
|
||||
|
||||
@Bean
|
||||
RouterFunction<?> mcpRouterFunction(WebFluxSseServerTransport transport) {
|
||||
return transport.getRouterFunction();
|
||||
RouterFunction<?> mcpRouterFunction(WebFluxSseServerTransportProvider transportProvider) {
|
||||
return transportProvider.getRouterFunction();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
|
@ -155,13 +168,13 @@ The transport layer in the MCP SDK is responsible for handling the communication
|
|||
@EnableWebMvc
|
||||
class McpConfig {
|
||||
@Bean
|
||||
WebMvcSseServerTransport webMvcSseServerTransport(ObjectMapper mapper) {
|
||||
return new WebMvcSseServerTransport(mapper, "/mcp/message");
|
||||
WebMvcSseServerTransportProvider webMvcSseServerTransportProvider(ObjectMapper mapper) {
|
||||
return new WebMvcSseServerTransportProvider(mapper, "/mcp/message");
|
||||
}
|
||||
|
||||
@Bean
|
||||
RouterFunction<ServerResponse> mcpRouterFunction(WebMvcSseServerTransport transport) {
|
||||
return transport.getRouterFunction();
|
||||
RouterFunction<ServerResponse> mcpRouterFunction(WebMvcSseServerTransportProvider transportProvider) {
|
||||
return transportProvider.getRouterFunction();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
|
@ -191,13 +204,13 @@ The transport layer in the MCP SDK is responsible for handling the communication
|
|||
public class McpServerConfig implements WebMvcConfigurer {
|
||||
|
||||
@Bean
|
||||
public HttpServletSseServerTransport servletSseServerTransport() {
|
||||
return new HttpServletSseServerTransport(new ObjectMapper(), "/mcp/message");
|
||||
public HttpServletSseServerTransportProvider servletSseServerTransportProvider() {
|
||||
return new HttpServletSseServerTransportProvider(new ObjectMapper(), "/mcp/message");
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ServletRegistrationBean customServletBean(HttpServletSseServerTransport servlet) {
|
||||
return new ServletRegistrationBean(servlet);
|
||||
public ServletRegistrationBean customServletBean(HttpServletSseServerTransportProvider transportProvider) {
|
||||
return new ServletRegistrationBean(transportProvider);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
|
@ -253,12 +266,16 @@ server.loggingNotification(LoggingMessageNotification.builder()
|
|||
Clients can control the minimum logging level they receive through the `mcpClient.setLoggingLevel(level)` request. Messages below the set level will be filtered out.
|
||||
Supported logging levels (in order of increasing severity): DEBUG (0), INFO (1), NOTICE (2), WARNING (3), ERROR (4), CRITICAL (5), ALERT (6), EMERGENCY (7)
|
||||
|
||||
### Tool Registration
|
||||
### Tool Specification
|
||||
|
||||
The Model Context Protocol allows servers to [expose tools](https://spec.modelcontextprotocol.io/specification/2024-11-05/server/tools/) that can be invoked by language models.
|
||||
The Java SDK allows implementing a Tool Specifications with their handler functions.
|
||||
Tools enable AI models to perform calculations, access external APIs, query databases, and manipulate files:
|
||||
|
||||
<Tabs>
|
||||
<Tab title="Sync">
|
||||
```java
|
||||
// Sync tool registration
|
||||
// Sync tool specification
|
||||
var schema = """
|
||||
{
|
||||
"type" : "object",
|
||||
|
|
@ -276,9 +293,9 @@ var schema = """
|
|||
}
|
||||
}
|
||||
""";
|
||||
var syncToolRegistration = new McpServerFeatures.SyncToolRegistration(
|
||||
var syncToolSpecification = new McpServerFeatures.SyncToolSpecificaiton(
|
||||
new Tool("calculator", "Basic calculator", schema),
|
||||
arguments -> {
|
||||
(exchange, arguments) -> {
|
||||
// Tool implementation
|
||||
return new CallToolResult(result, false);
|
||||
}
|
||||
|
|
@ -288,7 +305,7 @@ var syncToolRegistration = new McpServerFeatures.SyncToolRegistration(
|
|||
|
||||
<Tab title="Async">
|
||||
```java
|
||||
// Async tool registration
|
||||
// Async tool specification
|
||||
var schema = """
|
||||
{
|
||||
"type" : "object",
|
||||
|
|
@ -306,9 +323,9 @@ var schema = """
|
|||
}
|
||||
}
|
||||
""";
|
||||
var asyncToolRegistration = new McpServerFeatures.AsyncToolRegistration(
|
||||
var asyncToolSpecification = new McpServerFeatures.AsyncToolSpecificaiton(
|
||||
new Tool("calculator", "Basic calculator", schema),
|
||||
arguments -> {
|
||||
(exchange, arguments) -> {
|
||||
// Tool implementation
|
||||
return Mono.just(new CallToolResult(result, false));
|
||||
}
|
||||
|
|
@ -317,15 +334,22 @@ var asyncToolRegistration = new McpServerFeatures.AsyncToolRegistration(
|
|||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
### Resource Registration
|
||||
The Tool specification includes a Tool definition with `name`, `description`, and `parameter schema` followed by a call handler that implements the tool's logic.
|
||||
The function's first argument is `McpAsyncServerExchange` for client interaction, and the second is a map of tool arguments.
|
||||
|
||||
### Resource Specification
|
||||
|
||||
Specification of a resource with its handler function.
|
||||
Resources provide context to AI models by exposing data such as: File contents, Database records, API responses, System information, Application state.
|
||||
Example resource specification:
|
||||
|
||||
<Tabs>
|
||||
<Tab title="Sync">
|
||||
```java
|
||||
// Sync resource registration
|
||||
var syncResourceRegistration = new McpServerFeatures.SyncResourceRegistration(
|
||||
// Sync resource specification
|
||||
var syncResourceSpecification = new McpServerFeatures.syncResourceSpecification(
|
||||
new Resource("custom://resource", "name", "description", "mime-type", null),
|
||||
request -> {
|
||||
(exchange, request) -> {
|
||||
// Resource read implementation
|
||||
return new ReadResourceResult(contents);
|
||||
}
|
||||
|
|
@ -335,10 +359,10 @@ var syncResourceRegistration = new McpServerFeatures.SyncResourceRegistration(
|
|||
|
||||
<Tab title="Async">
|
||||
```java
|
||||
// Async resource registration
|
||||
var asyncResourceRegistration = new McpServerFeatures.AsyncResourceRegistration(
|
||||
// Async resource specification
|
||||
var asyncResourceSpecification = new McpServerFeatures.asyncResourceSpecification(
|
||||
new Resource("custom://resource", "name", "description", "mime-type", null),
|
||||
request -> {
|
||||
(exchange, request) -> {
|
||||
// Resource read implementation
|
||||
return Mono.just(new ReadResourceResult(contents));
|
||||
}
|
||||
|
|
@ -347,17 +371,26 @@ var asyncResourceRegistration = new McpServerFeatures.AsyncResourceRegistration(
|
|||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
### Prompt Registration
|
||||
The resource specification compriese of resource definitions and resource read handler.
|
||||
The resource definition including `name`, `description`, and `MIME type`.
|
||||
The first argument of the function that handles resource read requests is an `McpAsyncServerExchange` upon which the server can
|
||||
interact with the connected client.
|
||||
The second arguments is a `McpSchema.ReadResourceRequest`.
|
||||
|
||||
### Prompt Specification
|
||||
|
||||
As part of the [Prompting capabilities](https://spec.modelcontextprotocol.io/specification/2024-11-05/server/prompts/), MCP provides a standardized way for servers to expose prompt templates to clients.
|
||||
The Prompt Specification is a structured template for AI model interactions that enables consistent message formatting, parameter substitution, context injection, response formatting, and instruction templating.
|
||||
|
||||
<Tabs>
|
||||
<Tab title="Sync">
|
||||
```java
|
||||
// Sync prompt registration
|
||||
var syncPromptRegistration = new McpServerFeatures.SyncPromptRegistration(
|
||||
// Sync prompt specification
|
||||
var syncPromptSpecification = new McpServerFeatures.syncPromptSpecification(
|
||||
new Prompt("greeting", "description", List.of(
|
||||
new PromptArgument("name", "description", true)
|
||||
)),
|
||||
request -> {
|
||||
(exchange, request) -> {
|
||||
// Prompt implementation
|
||||
return new GetPromptResult(description, messages);
|
||||
}
|
||||
|
|
@ -367,12 +400,12 @@ var syncPromptRegistration = new McpServerFeatures.SyncPromptRegistration(
|
|||
|
||||
<Tab title="Async">
|
||||
```java
|
||||
// Async prompt registration
|
||||
var asyncPromptRegistration = new McpServerFeatures.AsyncPromptRegistration(
|
||||
// Async prompt specification
|
||||
var asyncPromptSpecification = new McpServerFeatures.asyncPromptSpecification(
|
||||
new Prompt("greeting", "description", List.of(
|
||||
new PromptArgument("name", "description", true)
|
||||
)),
|
||||
request -> {
|
||||
(exchange, request) -> {
|
||||
// Prompt implementation
|
||||
return Mono.just(new GetPromptResult(description, messages));
|
||||
}
|
||||
|
|
@ -381,6 +414,137 @@ var asyncPromptRegistration = new McpServerFeatures.AsyncPromptRegistration(
|
|||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
The prompt definition includes name (identifier for the prompt), description (purpose of the prompt), and list of arguments (parameters for templating).
|
||||
The handler function processes requests and returns formatted templates.
|
||||
The first argument is `McpAsyncServerExchange` for client interaction, and the second argument is a `GetPromptRequest` instance.
|
||||
|
||||
### Using Sampling from a Server
|
||||
|
||||
To use [Sampling capabilities](https://spec.modelcontextprotocol.io/specification/2024-11-05/client/sampling/), connect to a client that supports sampling.
|
||||
No special server configuration is needed, but verify client sampling support before making requests.
|
||||
Learn about [client sampling support](./mcp-client#sampling-support).
|
||||
|
||||
Once connected to a compatible client, the server can request language model generations:
|
||||
|
||||
<Tabs>
|
||||
<Tab title="Sync API">
|
||||
```java
|
||||
// Create a server
|
||||
McpSyncServer server = McpServer.sync(transportProvider)
|
||||
.serverInfo("my-server", "1.0.0")
|
||||
.build();
|
||||
|
||||
// Define a tool that uses sampling
|
||||
var calculatorTool = new McpServerFeatures.SyncToolSpecification(
|
||||
new Tool("ai-calculator", "Performs calculations using AI", schema),
|
||||
(exchange, arguments) -> {
|
||||
// Check if client supports sampling
|
||||
if (exchange.getClientCapabilities().sampling() == null) {
|
||||
return new CallToolResult("Client does not support AI capabilities", false);
|
||||
}
|
||||
|
||||
// Create a sampling request
|
||||
McpSchema.CreateMessageRequest request = McpSchema.CreateMessageRequest.builder()
|
||||
.content(new McpSchema.TextContent("Calculate: " + arguments.get("expression")))
|
||||
.modelPreferences(McpSchema.ModelPreferences.builder()
|
||||
.hints(List.of(
|
||||
McpSchema.ModelHint.of("claude-3-sonnet"),
|
||||
McpSchema.ModelHint.of("claude")
|
||||
))
|
||||
.intelligencePriority(0.8) // Prioritize intelligence
|
||||
.speedPriority(0.5) // Moderate speed importance
|
||||
.build())
|
||||
.systemPrompt("You are a helpful calculator assistant. Provide only the numerical answer.")
|
||||
.maxTokens(100)
|
||||
.build();
|
||||
|
||||
// Request sampling from the client
|
||||
McpSchema.CreateMessageResult result = exchange.createMessage(request);
|
||||
|
||||
// Process the result
|
||||
String answer = result.content().text();
|
||||
return new CallToolResult(answer, false);
|
||||
}
|
||||
);
|
||||
|
||||
// Add the tool to the server
|
||||
server.addTool(calculatorTool);
|
||||
```
|
||||
</Tab>
|
||||
|
||||
<Tab title="Async API">
|
||||
```java
|
||||
// Create a server
|
||||
McpAsyncServer server = McpServer.async(transportProvider)
|
||||
.serverInfo("my-server", "1.0.0")
|
||||
.build();
|
||||
|
||||
// Define a tool that uses sampling
|
||||
var calculatorTool = new McpServerFeatures.AsyncToolSpecification(
|
||||
new Tool("ai-calculator", "Performs calculations using AI", schema),
|
||||
(exchange, arguments) -> {
|
||||
// Check if client supports sampling
|
||||
if (exchange.getClientCapabilities().sampling() == null) {
|
||||
return Mono.just(new CallToolResult("Client does not support AI capabilities", false));
|
||||
}
|
||||
|
||||
// Create a sampling request
|
||||
McpSchema.CreateMessageRequest request = McpSchema.CreateMessageRequest.builder()
|
||||
.content(McpSchema.Content.builder()
|
||||
.type("text")
|
||||
.text("Calculate: " + arguments.get("expression"))
|
||||
.build())
|
||||
.modelPreferences(McpSchema.ModelPreferences.builder()
|
||||
.hints(List.of(
|
||||
McpSchema.ModelHint.builder().name("claude-3-sonnet").build(),
|
||||
McpSchema.ModelHint.builder().name("claude").build()
|
||||
))
|
||||
.intelligencePriority(0.8) // Prioritize intelligence
|
||||
.speedPriority(0.5) // Moderate speed importance
|
||||
.build())
|
||||
.systemPrompt("You are a helpful calculator assistant. Provide only the numerical answer.")
|
||||
.maxTokens(100)
|
||||
.build();
|
||||
|
||||
// Request sampling from the client
|
||||
return exchange.createMessage(request)
|
||||
.map(result -> {
|
||||
// Process the result
|
||||
String answer = result.content().text();
|
||||
return new CallToolResult(answer, false);
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
// Add the tool to the server
|
||||
server.addTool(calculatorTool)
|
||||
.subscribe();
|
||||
```
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
The `CreateMessageRequest` object allows you to specify: `Content` - the input text or image for the model,
|
||||
`Model Preferences` - hints and priorities for model selection, `System Prompt` - instructions for the model's behavior and `Max Tokens` - maximum length of the generated response
|
||||
|
||||
```java
|
||||
McpSchema.CreateMessageRequest request = McpSchema.CreateMessageRequest.builder()
|
||||
.content(McpSchema.Content.builder()
|
||||
.type("text")
|
||||
.text("What is the capital of France?")
|
||||
.build())
|
||||
.modelPreferences(McpSchema.ModelPreferences.builder()
|
||||
.hints(List.of(
|
||||
McpSchema.ModelHint.builder().name("claude-3-sonnet").build(),
|
||||
McpSchema.ModelHint.builder().name("claude").build()
|
||||
))
|
||||
.intelligencePriority(0.8)
|
||||
.speedPriority(0.5)
|
||||
.build())
|
||||
.systemPrompt("You are a helpful assistant.")
|
||||
.maxTokens(100)
|
||||
.build();
|
||||
```
|
||||
|
||||
## Error Handling
|
||||
|
||||
The SDK provides comprehensive error handling through the McpError class, covering protocol compatibility, transport communication, JSON-RPC messaging, tool execution, resource management, prompt handling, timeouts, and connection issues. This unified error handling approach ensures consistent and reliable error management across both synchronous and asynchronous operations.
|
||||
|
|
|
|||
Loading…
Reference in a new issue