feat(mcp): Add builder for CreateMessageRequest (#60)
- Implements a builder pattern for CreateMessageRequest - Updates corresponding tests to use the new builder syntax - Add ModelPreferences builder and ModelHint helper - Use builder pattern for CreateMessageRequest in integration tests Signed-off-by: Christian Tzolov <christian.tzolov@broadcom.com>
This commit is contained in:
parent
3e2139fa27
commit
33329bfabb
5 changed files with 163 additions and 32 deletions
|
|
@ -24,6 +24,7 @@ import io.modelcontextprotocol.spec.McpSchema.ClientCapabilities;
|
||||||
import io.modelcontextprotocol.spec.McpSchema.CreateMessageRequest;
|
import io.modelcontextprotocol.spec.McpSchema.CreateMessageRequest;
|
||||||
import io.modelcontextprotocol.spec.McpSchema.CreateMessageResult;
|
import io.modelcontextprotocol.spec.McpSchema.CreateMessageResult;
|
||||||
import io.modelcontextprotocol.spec.McpSchema.InitializeResult;
|
import io.modelcontextprotocol.spec.McpSchema.InitializeResult;
|
||||||
|
import io.modelcontextprotocol.spec.McpSchema.ModelPreferences;
|
||||||
import io.modelcontextprotocol.spec.McpSchema.Role;
|
import io.modelcontextprotocol.spec.McpSchema.Role;
|
||||||
import io.modelcontextprotocol.spec.McpSchema.Root;
|
import io.modelcontextprotocol.spec.McpSchema.Root;
|
||||||
import io.modelcontextprotocol.spec.McpSchema.ServerCapabilities;
|
import io.modelcontextprotocol.spec.McpSchema.ServerCapabilities;
|
||||||
|
|
@ -45,6 +46,7 @@ import org.springframework.web.reactive.function.server.RouterFunctions;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
import static org.awaitility.Awaitility.await;
|
import static org.awaitility.Awaitility.await;
|
||||||
|
import static org.junit.Assert.assertThat;
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
|
|
||||||
public class WebFluxSseIntegrationTests {
|
public class WebFluxSseIntegrationTests {
|
||||||
|
|
@ -142,13 +144,16 @@ public class WebFluxSseIntegrationTests {
|
||||||
McpServerFeatures.AsyncToolSpecification tool = new McpServerFeatures.AsyncToolSpecification(
|
McpServerFeatures.AsyncToolSpecification tool = new McpServerFeatures.AsyncToolSpecification(
|
||||||
new McpSchema.Tool("tool1", "tool1 description", emptyJsonSchema), (exchange, request) -> {
|
new McpSchema.Tool("tool1", "tool1 description", emptyJsonSchema), (exchange, request) -> {
|
||||||
|
|
||||||
var messages = List.of(new McpSchema.SamplingMessage(McpSchema.Role.USER,
|
var craeteMessageRequest = McpSchema.CreateMessageRequest.builder()
|
||||||
new McpSchema.TextContent("Test message")));
|
.messages(List.of(new McpSchema.SamplingMessage(McpSchema.Role.USER,
|
||||||
var modelPrefs = new McpSchema.ModelPreferences(List.of(), 1.0, 1.0, 1.0);
|
new McpSchema.TextContent("Test message"))))
|
||||||
|
.modelPreferences(ModelPreferences.builder()
|
||||||
var craeteMessageRequest = new McpSchema.CreateMessageRequest(messages, modelPrefs, null,
|
.hints(List.of())
|
||||||
McpSchema.CreateMessageRequest.ContextInclusionStrategy.NONE, null, 100, List.of(),
|
.costPriority(1.0)
|
||||||
Map.of());
|
.speedPriority(1.0)
|
||||||
|
.intelligencePriority(1.0)
|
||||||
|
.build())
|
||||||
|
.build();
|
||||||
|
|
||||||
StepVerifier.create(exchange.createMessage(craeteMessageRequest)).consumeNextWith(result -> {
|
StepVerifier.create(exchange.createMessage(craeteMessageRequest)).consumeNextWith(result -> {
|
||||||
assertThat(result).isNotNull();
|
assertThat(result).isNotNull();
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@ import io.modelcontextprotocol.spec.McpSchema.ClientCapabilities;
|
||||||
import io.modelcontextprotocol.spec.McpSchema.CreateMessageRequest;
|
import io.modelcontextprotocol.spec.McpSchema.CreateMessageRequest;
|
||||||
import io.modelcontextprotocol.spec.McpSchema.CreateMessageResult;
|
import io.modelcontextprotocol.spec.McpSchema.CreateMessageResult;
|
||||||
import io.modelcontextprotocol.spec.McpSchema.InitializeResult;
|
import io.modelcontextprotocol.spec.McpSchema.InitializeResult;
|
||||||
|
import io.modelcontextprotocol.spec.McpSchema.ModelPreferences;
|
||||||
import io.modelcontextprotocol.spec.McpSchema.Role;
|
import io.modelcontextprotocol.spec.McpSchema.Role;
|
||||||
import io.modelcontextprotocol.spec.McpSchema.Root;
|
import io.modelcontextprotocol.spec.McpSchema.Root;
|
||||||
import io.modelcontextprotocol.spec.McpSchema.ServerCapabilities;
|
import io.modelcontextprotocol.spec.McpSchema.ServerCapabilities;
|
||||||
|
|
@ -45,6 +46,7 @@ import org.springframework.web.servlet.function.ServerResponse;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
import static org.awaitility.Awaitility.await;
|
import static org.awaitility.Awaitility.await;
|
||||||
|
import static org.junit.Assert.assertThat;
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
|
|
||||||
public class WebMvcSseIntegrationTests {
|
public class WebMvcSseIntegrationTests {
|
||||||
|
|
@ -199,13 +201,16 @@ public class WebMvcSseIntegrationTests {
|
||||||
McpServerFeatures.AsyncToolSpecification tool = new McpServerFeatures.AsyncToolSpecification(
|
McpServerFeatures.AsyncToolSpecification tool = new McpServerFeatures.AsyncToolSpecification(
|
||||||
new McpSchema.Tool("tool1", "tool1 description", emptyJsonSchema), (exchange, request) -> {
|
new McpSchema.Tool("tool1", "tool1 description", emptyJsonSchema), (exchange, request) -> {
|
||||||
|
|
||||||
var messages = List.of(new McpSchema.SamplingMessage(McpSchema.Role.USER,
|
var craeteMessageRequest = McpSchema.CreateMessageRequest.builder()
|
||||||
new McpSchema.TextContent("Test message")));
|
.messages(List.of(new McpSchema.SamplingMessage(McpSchema.Role.USER,
|
||||||
var modelPrefs = new McpSchema.ModelPreferences(List.of(), 1.0, 1.0, 1.0);
|
new McpSchema.TextContent("Test message"))))
|
||||||
|
.modelPreferences(ModelPreferences.builder()
|
||||||
var craeteMessageRequest = new McpSchema.CreateMessageRequest(messages, modelPrefs, null,
|
.hints(List.of())
|
||||||
McpSchema.CreateMessageRequest.ContextInclusionStrategy.NONE, null, 100, List.of(),
|
.costPriority(1.0)
|
||||||
Map.of());
|
.speedPriority(1.0)
|
||||||
|
.intelligencePriority(1.0)
|
||||||
|
.build())
|
||||||
|
.build();
|
||||||
|
|
||||||
StepVerifier.create(exchange.createMessage(craeteMessageRequest)).consumeNextWith(result -> {
|
StepVerifier.create(exchange.createMessage(craeteMessageRequest)).consumeNextWith(result -> {
|
||||||
assertThat(result).isNotNull();
|
assertThat(result).isNotNull();
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@
|
||||||
package io.modelcontextprotocol.spec;
|
package io.modelcontextprotocol.spec;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
@ -767,11 +768,57 @@ public final class McpSchema {
|
||||||
@JsonProperty("costPriority") Double costPriority,
|
@JsonProperty("costPriority") Double costPriority,
|
||||||
@JsonProperty("speedPriority") Double speedPriority,
|
@JsonProperty("speedPriority") Double speedPriority,
|
||||||
@JsonProperty("intelligencePriority") Double intelligencePriority) {
|
@JsonProperty("intelligencePriority") Double intelligencePriority) {
|
||||||
} // @formatter:on
|
|
||||||
|
public static Builder builder() {
|
||||||
|
return new Builder();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Builder {
|
||||||
|
private List<ModelHint> hints;
|
||||||
|
private Double costPriority;
|
||||||
|
private Double speedPriority;
|
||||||
|
private Double intelligencePriority;
|
||||||
|
|
||||||
|
public Builder hints(List<ModelHint> hints) {
|
||||||
|
this.hints = hints;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder addHint(String name) {
|
||||||
|
if (this.hints == null) {
|
||||||
|
this.hints = new ArrayList<>();
|
||||||
|
}
|
||||||
|
this.hints.add(new ModelHint(name));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder costPriority(Double costPriority) {
|
||||||
|
this.costPriority = costPriority;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder speedPriority(Double speedPriority) {
|
||||||
|
this.speedPriority = speedPriority;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder intelligencePriority(Double intelligencePriority) {
|
||||||
|
this.intelligencePriority = intelligencePriority;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ModelPreferences build() {
|
||||||
|
return new ModelPreferences(hints, costPriority, speedPriority, intelligencePriority);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // @formatter:on
|
||||||
|
|
||||||
@JsonInclude(JsonInclude.Include.NON_ABSENT)
|
@JsonInclude(JsonInclude.Include.NON_ABSENT)
|
||||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||||
public record ModelHint(@JsonProperty("name") String name) {
|
public record ModelHint(@JsonProperty("name") String name) {
|
||||||
|
public static ModelHint of(String name) {
|
||||||
|
return new ModelHint(name);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsonInclude(JsonInclude.Include.NON_ABSENT)
|
@JsonInclude(JsonInclude.Include.NON_ABSENT)
|
||||||
|
|
@ -799,6 +846,66 @@ public final class McpSchema {
|
||||||
@JsonProperty("thisServer") THIS_SERVER,
|
@JsonProperty("thisServer") THIS_SERVER,
|
||||||
@JsonProperty("allServers") ALL_SERVERS
|
@JsonProperty("allServers") ALL_SERVERS
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Builder builder() {
|
||||||
|
return new Builder();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Builder {
|
||||||
|
private List<SamplingMessage> messages;
|
||||||
|
private ModelPreferences modelPreferences;
|
||||||
|
private String systemPrompt;
|
||||||
|
private ContextInclusionStrategy includeContext;
|
||||||
|
private Double temperature;
|
||||||
|
private int maxTokens;
|
||||||
|
private List<String> stopSequences;
|
||||||
|
private Map<String, Object> metadata;
|
||||||
|
|
||||||
|
public Builder messages(List<SamplingMessage> messages) {
|
||||||
|
this.messages = messages;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder modelPreferences(ModelPreferences modelPreferences) {
|
||||||
|
this.modelPreferences = modelPreferences;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder systemPrompt(String systemPrompt) {
|
||||||
|
this.systemPrompt = systemPrompt;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder includeContext(ContextInclusionStrategy includeContext) {
|
||||||
|
this.includeContext = includeContext;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder temperature(Double temperature) {
|
||||||
|
this.temperature = temperature;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder maxTokens(int maxTokens) {
|
||||||
|
this.maxTokens = maxTokens;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder stopSequences(List<String> stopSequences) {
|
||||||
|
this.stopSequences = stopSequences;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder metadata(Map<String, Object> metadata) {
|
||||||
|
this.metadata = metadata;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CreateMessageRequest build() {
|
||||||
|
return new CreateMessageRequest(messages, modelPreferences, systemPrompt,
|
||||||
|
includeContext, temperature, maxTokens, stopSequences, metadata);
|
||||||
|
}
|
||||||
|
}
|
||||||
}// @formatter:on
|
}// @formatter:on
|
||||||
|
|
||||||
@JsonInclude(JsonInclude.Include.NON_ABSENT)
|
@JsonInclude(JsonInclude.Include.NON_ABSENT)
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ import io.modelcontextprotocol.spec.McpSchema.ClientCapabilities;
|
||||||
import io.modelcontextprotocol.spec.McpSchema.CreateMessageRequest;
|
import io.modelcontextprotocol.spec.McpSchema.CreateMessageRequest;
|
||||||
import io.modelcontextprotocol.spec.McpSchema.CreateMessageResult;
|
import io.modelcontextprotocol.spec.McpSchema.CreateMessageResult;
|
||||||
import io.modelcontextprotocol.spec.McpSchema.InitializeResult;
|
import io.modelcontextprotocol.spec.McpSchema.InitializeResult;
|
||||||
|
import io.modelcontextprotocol.spec.McpSchema.ModelPreferences;
|
||||||
import io.modelcontextprotocol.spec.McpSchema.Role;
|
import io.modelcontextprotocol.spec.McpSchema.Role;
|
||||||
import io.modelcontextprotocol.spec.McpSchema.Root;
|
import io.modelcontextprotocol.spec.McpSchema.Root;
|
||||||
import io.modelcontextprotocol.spec.McpSchema.ServerCapabilities;
|
import io.modelcontextprotocol.spec.McpSchema.ServerCapabilities;
|
||||||
|
|
@ -162,13 +163,16 @@ public class HttpServletSseServerTransportProviderIntegrationTests {
|
||||||
McpServerFeatures.AsyncToolSpecification tool = new McpServerFeatures.AsyncToolSpecification(
|
McpServerFeatures.AsyncToolSpecification tool = new McpServerFeatures.AsyncToolSpecification(
|
||||||
new McpSchema.Tool("tool1", "tool1 description", emptyJsonSchema), (exchange, request) -> {
|
new McpSchema.Tool("tool1", "tool1 description", emptyJsonSchema), (exchange, request) -> {
|
||||||
|
|
||||||
var messages = List.of(new McpSchema.SamplingMessage(McpSchema.Role.USER,
|
var craeteMessageRequest = McpSchema.CreateMessageRequest.builder()
|
||||||
new McpSchema.TextContent("Test message")));
|
.messages(List.of(new McpSchema.SamplingMessage(McpSchema.Role.USER,
|
||||||
var modelPrefs = new McpSchema.ModelPreferences(List.of(), 1.0, 1.0, 1.0);
|
new McpSchema.TextContent("Test message"))))
|
||||||
|
.modelPreferences(ModelPreferences.builder()
|
||||||
var craeteMessageRequest = new McpSchema.CreateMessageRequest(messages, modelPrefs, null,
|
.hints(List.of())
|
||||||
McpSchema.CreateMessageRequest.ContextInclusionStrategy.NONE, null, 100, List.of(),
|
.costPriority(1.0)
|
||||||
Map.of());
|
.speedPriority(1.0)
|
||||||
|
.intelligencePriority(1.0)
|
||||||
|
.build())
|
||||||
|
.build();
|
||||||
|
|
||||||
StepVerifier.create(exchange.createMessage(craeteMessageRequest)).consumeNextWith(result -> {
|
StepVerifier.create(exchange.createMessage(craeteMessageRequest)).consumeNextWith(result -> {
|
||||||
assertThat(result).isNotNull();
|
assertThat(result).isNotNull();
|
||||||
|
|
|
||||||
|
|
@ -524,10 +524,16 @@ public class McpSchemaTests {
|
||||||
Map<String, Object> metadata = new HashMap<>();
|
Map<String, Object> metadata = new HashMap<>();
|
||||||
metadata.put("session", "test-session");
|
metadata.put("session", "test-session");
|
||||||
|
|
||||||
McpSchema.CreateMessageRequest request = new McpSchema.CreateMessageRequest(Collections.singletonList(message),
|
McpSchema.CreateMessageRequest request = McpSchema.CreateMessageRequest.builder()
|
||||||
preferences, "You are a helpful assistant",
|
.messages(Collections.singletonList(message))
|
||||||
McpSchema.CreateMessageRequest.ContextInclusionStrategy.THIS_SERVER, 0.7, 1000,
|
.modelPreferences(preferences)
|
||||||
Arrays.asList("STOP", "END"), metadata);
|
.systemPrompt("You are a helpful assistant")
|
||||||
|
.includeContext(McpSchema.CreateMessageRequest.ContextInclusionStrategy.THIS_SERVER)
|
||||||
|
.temperature(0.7)
|
||||||
|
.maxTokens(1000)
|
||||||
|
.stopSequences(Arrays.asList("STOP", "END"))
|
||||||
|
.metadata(metadata)
|
||||||
|
.build();
|
||||||
|
|
||||||
String value = mapper.writeValueAsString(request);
|
String value = mapper.writeValueAsString(request);
|
||||||
|
|
||||||
|
|
@ -543,8 +549,12 @@ public class McpSchemaTests {
|
||||||
void testCreateMessageResult() throws Exception {
|
void testCreateMessageResult() throws Exception {
|
||||||
McpSchema.TextContent content = new McpSchema.TextContent("Assistant response");
|
McpSchema.TextContent content = new McpSchema.TextContent("Assistant response");
|
||||||
|
|
||||||
McpSchema.CreateMessageResult result = new McpSchema.CreateMessageResult(McpSchema.Role.ASSISTANT, content,
|
McpSchema.CreateMessageResult result = McpSchema.CreateMessageResult.builder()
|
||||||
"gpt-4", McpSchema.CreateMessageResult.StopReason.END_TURN);
|
.role(McpSchema.Role.ASSISTANT)
|
||||||
|
.content(content)
|
||||||
|
.model("gpt-4")
|
||||||
|
.stopReason(McpSchema.CreateMessageResult.StopReason.END_TURN)
|
||||||
|
.build();
|
||||||
|
|
||||||
String value = mapper.writeValueAsString(result);
|
String value = mapper.writeValueAsString(result);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue