refactor: update MCP API usage to version 0.8.0
- Remove all book-library MCP examples (servlet, webflux, and webmvc implementations) - Update weather example to use MCP version 0.8.0-SNAPSHOT - Refactor transport handling to use transport providers instead of direct transport objects - Update method calls from toSyncToolRegistration to toSyncToolSpecifications - Add central-portal-snapshots repository to pom.xml for dependency resolution - Align with the new MCP client class names Add MCP Sampling capability with weather example Adds MCP Sampling implementation that demonstrates how to delegate LLM requests to multiple providers. - add a weather server that retrieves data and uses MCP Sampling to generate creative content - add a client that routes requests to different LLM providers (OpenAI and Anthropic) based on model hints - add README documentation explaining the MCP Sampling workflow and implementation details The MCP Sampling capability enables applications to leverage multiple LLM providers within a single workflow, allowing for creative content generation, model comparison, and specialized task delegation. refactor: migrate to spring-ai-mcp-client-spring-boot-starter - Replace spring-ai-mcp dependency with spring-ai-mcp-client-spring-boot-starter - Update import statements from org.springframework.ai.mcp.* to io.modelcontextprotocol.client.* - Replace McpFunctionCallback with SyncMcpToolCallbackProvider - Update Spring AI version from 1.0.0-M5 to 1.0.0-SNAPSHOT in multiple projects - Enable tool callback auto-configuration with spring.ai.mcp.client.toolcallback.enabled refactor: update Spring AI artifact IDs to new naming convention - Update all Spring AI dependencies to use the new naming convention: spring-ai-*-spring-boot-starter → spring-ai-starter-* spring-ai-openai-spring-boot-starter → spring-ai-starter-model-openai spring-ai-mcp-client-spring-boot-starter → spring-ai-starter-mcp-client - And similar patterns for other artifacts - Enable debug mode in brave module's application.properties Signed-off-by: Christian Tzolov <christian.tzolov@broadcom.com>
This commit is contained in:
committed by
Mark Pollack
parent
1ca981eba5
commit
41c921bc33
190
model-context-protocol/sampling/README.md
Normal file
190
model-context-protocol/sampling/README.md
Normal file
@@ -0,0 +1,190 @@
|
||||
# Spring AI MCP Sampling Examples
|
||||
|
||||
This directory contains examples demonstrating the Model Context Protocol (MCP) Sampling capability in Spring AI. MCP Sampling allows an MCP server to delegate certain requests to LLM providers, enabling multi-model interactions and creative content generation.
|
||||
|
||||
## Overview
|
||||
|
||||
The MCP Sampling examples showcase:
|
||||
|
||||
- How an MCP server can delegate LLM requests to a client
|
||||
- How a client can route requests to different LLM providers based on model hints
|
||||
- Integration with multiple LLM providers (OpenAI and Anthropic)
|
||||
- Creative content generation using multiple models
|
||||
- Combining responses from different LLMs into a unified result
|
||||
|
||||
## Projects
|
||||
|
||||
This directory contains two main projects:
|
||||
|
||||
1. **[mcp-weather-webmvc-server](./mcp-weather-webmvc-server)**: An MCP server that provides weather information and uses MCP Sampling to generate creative content
|
||||
2. **[mcp-sampling-client](./mcp-sampling-client)**: An MCP client that handles sampling requests and routes them to different LLM providers
|
||||
|
||||
## What is MCP Sampling?
|
||||
|
||||
MCP Sampling is a powerful capability of the Model Context Protocol that allows:
|
||||
|
||||
- An MCP server to delegate certain requests to LLM providers
|
||||
- Specifying model preferences to target specific LLM providers
|
||||
- Routing requests based on model hints
|
||||
- Combining responses from multiple LLMs
|
||||
|
||||
This approach enables applications to leverage multiple LLM providers within a single workflow, allowing for creative content generation, model comparison, and specialized task delegation.
|
||||
|
||||
## How It Works
|
||||
|
||||
The MCP Sampling workflow in these examples follows these steps:
|
||||
|
||||
1. **Client Initialization**:
|
||||
- The client connects to the MCP Weather Server
|
||||
- It registers a sampling handler that can route requests to different LLM providers
|
||||
|
||||
2. **User Query**:
|
||||
- The user sends a weather-related query to the client
|
||||
- The client forwards the query to the MCP Weather Server
|
||||
|
||||
3. **Server Processing**:
|
||||
- The server retrieves weather data from the Open-Meteo API
|
||||
- It extracts the `McpSyncServerExchange` from the tool context
|
||||
- It creates sampling requests with different model preferences:
|
||||
- One targeting OpenAI with `ModelPreferences.builder().addHint("openai").build()`
|
||||
- One targeting Anthropic with `ModelPreferences.builder().addHint("anthropic").build()`
|
||||
|
||||
4. **Sampling Delegation**:
|
||||
- The server sends the sampling requests back to the client
|
||||
- The client's sampling handler receives the requests
|
||||
|
||||
5. **Model Routing**:
|
||||
- The client extracts the model hint from each request
|
||||
- It selects the appropriate LLM provider based on the hint
|
||||
- It forwards the prompt to the selected LLM
|
||||
|
||||
6. **Response Generation**:
|
||||
- Each LLM generates a creative response (in this case, a poem about the weather)
|
||||
- The client returns the responses to the server
|
||||
|
||||
7. **Result Combination**:
|
||||
- The server combines the responses from different LLMs
|
||||
- It returns the combined result to the user
|
||||
|
||||
## Server Implementation
|
||||
|
||||
The MCP Weather Server implements the server-side of MCP Sampling:
|
||||
|
||||
```java
|
||||
public String callMcpSampling(ToolContext toolContext, WeatherResponse weatherResponse) {
|
||||
String openAiWeatherPoem = "<no OpenAI poem>";
|
||||
String anthropicWeatherPoem = "<no Anthropic poem>";
|
||||
|
||||
if (toolContext != null && toolContext.getContext().containsKey("exchange")) {
|
||||
// Spring AI MCP Auto-configuration injects the McpSyncServerExchange into the ToolContext
|
||||
McpSyncServerExchange exchange = (McpSyncServerExchange) toolContext.getContext().get("exchange");
|
||||
if (exchange.getClientCapabilities().sampling() != null) {
|
||||
var messageRequestBuilder = McpSchema.CreateMessageRequest.builder()
|
||||
.systemPrompt("You are a poet!")
|
||||
.messages(List.of(new McpSchema.SamplingMessage(McpSchema.Role.USER,
|
||||
new McpSchema.TextContent(
|
||||
"Please write a poem about this weather forecast (temperature is in Celsius)..."))));
|
||||
|
||||
// Request poem from OpenAI
|
||||
var openAiLlmMessageRequest = messageRequestBuilder
|
||||
.modelPreferences(ModelPreferences.builder().addHint("openai").build())
|
||||
.build();
|
||||
CreateMessageResult openAiLlmResponse = exchange.createMessage(openAiLlmMessageRequest);
|
||||
openAiWeatherPoem = ((McpSchema.TextContent) openAiLlmResponse.content()).text();
|
||||
|
||||
// Request poem from Anthropic
|
||||
var anthropicLlmMessageRequest = messageRequestBuilder
|
||||
.modelPreferences(ModelPreferences.builder().addHint("anthropic").build())
|
||||
.build();
|
||||
CreateMessageResult anthropicAiLlmResponse = exchange.createMessage(anthropicLlmMessageRequest);
|
||||
anthropicWeatherPoem = ((McpSchema.TextContent) anthropicAiLlmResponse.content()).text();
|
||||
}
|
||||
}
|
||||
|
||||
// Combine responses
|
||||
return "OpenAI poem about the weather: " + openAiWeatherPoem + "\n\n" +
|
||||
"Anthropic poem about the weather: " + anthropicWeatherPoem + "\n" +
|
||||
ModelOptionsUtils.toJsonStringPrettyPrinter(weatherResponse);
|
||||
}
|
||||
```
|
||||
|
||||
## Client Implementation
|
||||
|
||||
The MCP Sampling Client implements the client-side handling of sampling requests:
|
||||
|
||||
```java
|
||||
@Bean
|
||||
McpSyncClientCustomizer samplingCustomizer(Map<String, ChatClient> chatClients) {
|
||||
return (name, spec) -> {
|
||||
spec.sampling(llmRequest -> {
|
||||
var userPrompt = ((McpSchema.TextContent) llmRequest.messages().get(0).content()).text();
|
||||
String modelHint = llmRequest.modelPreferences().hints().get(0).name();
|
||||
|
||||
// Find the appropriate chat client based on the model hint
|
||||
ChatClient hintedChatClient = chatClients.entrySet().stream()
|
||||
.filter(e -> e.getKey().contains(modelHint)).findFirst()
|
||||
.orElseThrow().getValue();
|
||||
|
||||
// Generate response using the selected model
|
||||
String response = hintedChatClient.prompt()
|
||||
.system(llmRequest.systemPrompt())
|
||||
.user(userPrompt)
|
||||
.call()
|
||||
.content();
|
||||
|
||||
return CreateMessageResult.builder().content(new McpSchema.TextContent(response)).build();
|
||||
});
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
## Running the Examples
|
||||
|
||||
### Prerequisites
|
||||
|
||||
- Java 17 or later
|
||||
- Maven 3.6+
|
||||
- OpenAI API key
|
||||
- Anthropic API key
|
||||
|
||||
### Step 1: Start the MCP Weather Server
|
||||
|
||||
```bash
|
||||
cd mcp-weather-webmvc-server
|
||||
./mvnw clean install -DskipTests
|
||||
java -jar target/mcp-sampling-weather-server-0.0.1-SNAPSHOT.jar
|
||||
```
|
||||
|
||||
### Step 2: Set Environment Variables
|
||||
|
||||
```bash
|
||||
export OPENAI_API_KEY=your-openai-key
|
||||
export ANTHROPIC_API_KEY=your-anthropic-key
|
||||
```
|
||||
|
||||
### Step 3: Run the MCP Sampling Client
|
||||
|
||||
```bash
|
||||
cd mcp-sampling-client
|
||||
./mvnw clean install
|
||||
java -Dai.user.input='What is the weather in Amsterdam right now?' -jar target/mcp-sampling-client-0.0.1-SNAPSHOT.jar
|
||||
```
|
||||
|
||||
## Sample Output
|
||||
|
||||
When you run the application, you'll see creative responses from both OpenAI and Anthropic models, each generating a poem about the current weather in Amsterdam.
|
||||
|
||||
## Related Projects
|
||||
|
||||
Spring AI provides several MCP client and server implementations:
|
||||
|
||||
- **[starter-default-client](../client-starter/starter-default-client)**: A default MCP client implementation using Spring Boot
|
||||
- **[starter-webflux-client](../client-starter/starter-webflux-client)**: An MCP client implementation using Spring WebFlux
|
||||
|
||||
## Additional Resources
|
||||
|
||||
* [Spring AI Documentation](https://docs.spring.io/spring-ai/reference/)
|
||||
* [MCP Server Boot Starter](https://docs.spring.io/spring-ai/reference/api/mcp/mcp-server-boot-starter-docs.html)
|
||||
* [MCP Client Boot Starter](https://docs.spring.io/spring-ai/reference/api/mcp/mcp-client-boot-starter-docs.html)
|
||||
* [Model Context Protocol Specification](https://modelcontextprotocol.github.io/specification/)
|
||||
* [Spring Boot Documentation](https://docs.spring.io/spring-boot/docs/current/reference/html/)
|
||||
Reference in New Issue
Block a user