feat: Add elicitation support to MCP protocol
Implement elicitation capabilities allowing servers to request additional information from users through clients during interactions. This feature provides a standardized way for servers to gather necessary information dynamically while clients maintain control over user interactions and data sharing. - Add ElicitRequest and ElicitResult classes to McpSchema - Implement elicitation handlers in client classes - Add elicitation capabilities to server exchange classes - Add tests for elicitation functionality with various scenarios
This commit is contained in:
parent
07e7b8fd6b
commit
8a5a591d39
6 changed files with 1106 additions and 28 deletions
|
|
@ -23,6 +23,8 @@ import io.modelcontextprotocol.spec.McpSchema;
|
|||
import io.modelcontextprotocol.spec.McpSchema.ClientCapabilities;
|
||||
import io.modelcontextprotocol.spec.McpSchema.CreateMessageRequest;
|
||||
import io.modelcontextprotocol.spec.McpSchema.CreateMessageResult;
|
||||
import io.modelcontextprotocol.spec.McpSchema.ElicitRequest;
|
||||
import io.modelcontextprotocol.spec.McpSchema.ElicitResult;
|
||||
import io.modelcontextprotocol.spec.McpSchema.GetPromptRequest;
|
||||
import io.modelcontextprotocol.spec.McpSchema.GetPromptResult;
|
||||
import io.modelcontextprotocol.spec.McpSchema.ListPromptsResult;
|
||||
|
|
@ -141,6 +143,15 @@ public class McpAsyncClient {
|
|||
*/
|
||||
private Function<CreateMessageRequest, Mono<CreateMessageResult>> samplingHandler;
|
||||
|
||||
/**
|
||||
* MCP provides a standardized way for servers to request additional information from
|
||||
* users through the client during interactions. This flow allows clients to maintain
|
||||
* control over user interactions and data sharing while enabling servers to gather
|
||||
* necessary information dynamically. Servers can request structured data from users
|
||||
* with optional JSON schemas to validate responses.
|
||||
*/
|
||||
private Function<ElicitRequest, Mono<ElicitResult>> elicitationHandler;
|
||||
|
||||
/**
|
||||
* Client transport implementation.
|
||||
*/
|
||||
|
|
@ -189,6 +200,15 @@ public class McpAsyncClient {
|
|||
requestHandlers.put(McpSchema.METHOD_SAMPLING_CREATE_MESSAGE, samplingCreateMessageHandler());
|
||||
}
|
||||
|
||||
// Elicitation Handler
|
||||
if (this.clientCapabilities.elicitation() != null) {
|
||||
if (features.elicitationHandler() == null) {
|
||||
throw new McpError("Elicitation handler must not be null when client capabilities include elicitation");
|
||||
}
|
||||
this.elicitationHandler = features.elicitationHandler();
|
||||
requestHandlers.put(McpSchema.METHOD_ELICITATION_CREATE, elicitationCreateHandler());
|
||||
}
|
||||
|
||||
// Notification Handlers
|
||||
Map<String, NotificationHandler> notificationHandlers = new HashMap<>();
|
||||
|
||||
|
|
@ -500,6 +520,18 @@ public class McpAsyncClient {
|
|||
};
|
||||
}
|
||||
|
||||
// --------------------------
|
||||
// Elicitation
|
||||
// --------------------------
|
||||
private RequestHandler<ElicitResult> elicitationCreateHandler() {
|
||||
return params -> {
|
||||
ElicitRequest request = transport.unmarshalFrom(params, new TypeReference<>() {
|
||||
});
|
||||
|
||||
return this.elicitationHandler.apply(request);
|
||||
};
|
||||
}
|
||||
|
||||
// --------------------------
|
||||
// Tools
|
||||
// --------------------------
|
||||
|
|
|
|||
|
|
@ -18,6 +18,8 @@ import io.modelcontextprotocol.spec.McpTransport;
|
|||
import io.modelcontextprotocol.spec.McpSchema.ClientCapabilities;
|
||||
import io.modelcontextprotocol.spec.McpSchema.CreateMessageRequest;
|
||||
import io.modelcontextprotocol.spec.McpSchema.CreateMessageResult;
|
||||
import io.modelcontextprotocol.spec.McpSchema.ElicitRequest;
|
||||
import io.modelcontextprotocol.spec.McpSchema.ElicitResult;
|
||||
import io.modelcontextprotocol.spec.McpSchema.Implementation;
|
||||
import io.modelcontextprotocol.spec.McpSchema.Root;
|
||||
import io.modelcontextprotocol.util.Assert;
|
||||
|
|
@ -175,6 +177,8 @@ public interface McpClient {
|
|||
|
||||
private Function<CreateMessageRequest, CreateMessageResult> samplingHandler;
|
||||
|
||||
private Function<ElicitRequest, ElicitResult> elicitationHandler;
|
||||
|
||||
private SyncSpec(McpClientTransport transport) {
|
||||
Assert.notNull(transport, "Transport must not be null");
|
||||
this.transport = transport;
|
||||
|
|
@ -283,6 +287,21 @@ public interface McpClient {
|
|||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a custom elicitation handler for processing elicitation message requests.
|
||||
* The elicitation handler can modify or validate messages before they are sent to
|
||||
* the server, enabling custom processing logic.
|
||||
* @param elicitationHandler A function that processes elicitation requests and
|
||||
* returns results. Must not be null.
|
||||
* @return This builder instance for method chaining
|
||||
* @throws IllegalArgumentException if elicitationHandler is null
|
||||
*/
|
||||
public SyncSpec elicitation(Function<ElicitRequest, ElicitResult> elicitationHandler) {
|
||||
Assert.notNull(elicitationHandler, "Elicitation handler must not be null");
|
||||
this.elicitationHandler = elicitationHandler;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a consumer to be notified when the available tools change. This allows the
|
||||
* client to react to changes in the server's tool capabilities, such as tools
|
||||
|
|
@ -364,7 +383,7 @@ public interface McpClient {
|
|||
public McpSyncClient build() {
|
||||
McpClientFeatures.Sync syncFeatures = new McpClientFeatures.Sync(this.clientInfo, this.capabilities,
|
||||
this.roots, this.toolsChangeConsumers, this.resourcesChangeConsumers, this.promptsChangeConsumers,
|
||||
this.loggingConsumers, this.samplingHandler);
|
||||
this.loggingConsumers, this.samplingHandler, this.elicitationHandler);
|
||||
|
||||
McpClientFeatures.Async asyncFeatures = McpClientFeatures.Async.fromSync(syncFeatures);
|
||||
|
||||
|
|
@ -414,6 +433,8 @@ public interface McpClient {
|
|||
|
||||
private Function<CreateMessageRequest, Mono<CreateMessageResult>> samplingHandler;
|
||||
|
||||
private Function<ElicitRequest, Mono<ElicitResult>> elicitationHandler;
|
||||
|
||||
private AsyncSpec(McpClientTransport transport) {
|
||||
Assert.notNull(transport, "Transport must not be null");
|
||||
this.transport = transport;
|
||||
|
|
@ -522,6 +543,21 @@ public interface McpClient {
|
|||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a custom elicitation handler for processing elicitation message requests.
|
||||
* The elicitation handler can modify or validate messages before they are sent to
|
||||
* the server, enabling custom processing logic.
|
||||
* @param elicitationHandler A function that processes elicitation requests and
|
||||
* returns results. Must not be null.
|
||||
* @return This builder instance for method chaining
|
||||
* @throws IllegalArgumentException if elicitationHandler is null
|
||||
*/
|
||||
public AsyncSpec elicitation(Function<ElicitRequest, Mono<ElicitResult>> elicitationHandler) {
|
||||
Assert.notNull(elicitationHandler, "Elicitation handler must not be null");
|
||||
this.elicitationHandler = elicitationHandler;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a consumer to be notified when the available tools change. This allows the
|
||||
* client to react to changes in the server's tool capabilities, such as tools
|
||||
|
|
@ -606,7 +642,7 @@ public interface McpClient {
|
|||
return new McpAsyncClient(this.transport, this.requestTimeout, this.initializationTimeout,
|
||||
new McpClientFeatures.Async(this.clientInfo, this.capabilities, this.roots,
|
||||
this.toolsChangeConsumers, this.resourcesChangeConsumers, this.promptsChangeConsumers,
|
||||
this.loggingConsumers, this.samplingHandler));
|
||||
this.loggingConsumers, this.samplingHandler, this.elicitationHandler));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -60,13 +60,15 @@ class McpClientFeatures {
|
|||
* @param promptsChangeConsumers the prompts change consumers.
|
||||
* @param loggingConsumers the logging consumers.
|
||||
* @param samplingHandler the sampling handler.
|
||||
* @param elicitationHandler the elicitation handler.
|
||||
*/
|
||||
record Async(McpSchema.Implementation clientInfo, McpSchema.ClientCapabilities clientCapabilities,
|
||||
Map<String, McpSchema.Root> roots, List<Function<List<McpSchema.Tool>, Mono<Void>>> toolsChangeConsumers,
|
||||
List<Function<List<McpSchema.Resource>, Mono<Void>>> resourcesChangeConsumers,
|
||||
List<Function<List<McpSchema.Prompt>, Mono<Void>>> promptsChangeConsumers,
|
||||
List<Function<McpSchema.LoggingMessageNotification, Mono<Void>>> loggingConsumers,
|
||||
Function<McpSchema.CreateMessageRequest, Mono<McpSchema.CreateMessageResult>> samplingHandler) {
|
||||
Function<McpSchema.CreateMessageRequest, Mono<McpSchema.CreateMessageResult>> samplingHandler,
|
||||
Function<McpSchema.ElicitRequest, Mono<McpSchema.ElicitResult>> elicitationHandler) {
|
||||
|
||||
/**
|
||||
* Create an instance and validate the arguments.
|
||||
|
|
@ -77,6 +79,7 @@ class McpClientFeatures {
|
|||
* @param promptsChangeConsumers the prompts change consumers.
|
||||
* @param loggingConsumers the logging consumers.
|
||||
* @param samplingHandler the sampling handler.
|
||||
* @param elicitationHandler the elicitation handler.
|
||||
*/
|
||||
public Async(McpSchema.Implementation clientInfo, McpSchema.ClientCapabilities clientCapabilities,
|
||||
Map<String, McpSchema.Root> roots,
|
||||
|
|
@ -84,14 +87,16 @@ class McpClientFeatures {
|
|||
List<Function<List<McpSchema.Resource>, Mono<Void>>> resourcesChangeConsumers,
|
||||
List<Function<List<McpSchema.Prompt>, Mono<Void>>> promptsChangeConsumers,
|
||||
List<Function<McpSchema.LoggingMessageNotification, Mono<Void>>> loggingConsumers,
|
||||
Function<McpSchema.CreateMessageRequest, Mono<McpSchema.CreateMessageResult>> samplingHandler) {
|
||||
Function<McpSchema.CreateMessageRequest, Mono<McpSchema.CreateMessageResult>> samplingHandler,
|
||||
Function<McpSchema.ElicitRequest, Mono<McpSchema.ElicitResult>> elicitationHandler) {
|
||||
|
||||
Assert.notNull(clientInfo, "Client info must not be null");
|
||||
this.clientInfo = clientInfo;
|
||||
this.clientCapabilities = (clientCapabilities != null) ? clientCapabilities
|
||||
: new McpSchema.ClientCapabilities(null,
|
||||
!Utils.isEmpty(roots) ? new McpSchema.ClientCapabilities.RootCapabilities(false) : null,
|
||||
samplingHandler != null ? new McpSchema.ClientCapabilities.Sampling() : null);
|
||||
samplingHandler != null ? new McpSchema.ClientCapabilities.Sampling() : null,
|
||||
elicitationHandler != null ? new McpSchema.ClientCapabilities.Elicitation() : null);
|
||||
this.roots = roots != null ? new ConcurrentHashMap<>(roots) : new ConcurrentHashMap<>();
|
||||
|
||||
this.toolsChangeConsumers = toolsChangeConsumers != null ? toolsChangeConsumers : List.of();
|
||||
|
|
@ -99,6 +104,7 @@ class McpClientFeatures {
|
|||
this.promptsChangeConsumers = promptsChangeConsumers != null ? promptsChangeConsumers : List.of();
|
||||
this.loggingConsumers = loggingConsumers != null ? loggingConsumers : List.of();
|
||||
this.samplingHandler = samplingHandler;
|
||||
this.elicitationHandler = elicitationHandler;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -138,9 +144,14 @@ class McpClientFeatures {
|
|||
Function<McpSchema.CreateMessageRequest, Mono<McpSchema.CreateMessageResult>> samplingHandler = r -> Mono
|
||||
.fromCallable(() -> syncSpec.samplingHandler().apply(r))
|
||||
.subscribeOn(Schedulers.boundedElastic());
|
||||
|
||||
Function<McpSchema.ElicitRequest, Mono<McpSchema.ElicitResult>> elicitationHandler = r -> Mono
|
||||
.fromCallable(() -> syncSpec.elicitationHandler().apply(r))
|
||||
.subscribeOn(Schedulers.boundedElastic());
|
||||
|
||||
return new Async(syncSpec.clientInfo(), syncSpec.clientCapabilities(), syncSpec.roots(),
|
||||
toolsChangeConsumers, resourcesChangeConsumers, promptsChangeConsumers, loggingConsumers,
|
||||
samplingHandler);
|
||||
samplingHandler, elicitationHandler);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -156,13 +167,15 @@ class McpClientFeatures {
|
|||
* @param promptsChangeConsumers the prompts change consumers.
|
||||
* @param loggingConsumers the logging consumers.
|
||||
* @param samplingHandler the sampling handler.
|
||||
* @param elicitationHandler the elicitation handler.
|
||||
*/
|
||||
public record Sync(McpSchema.Implementation clientInfo, McpSchema.ClientCapabilities clientCapabilities,
|
||||
Map<String, McpSchema.Root> roots, List<Consumer<List<McpSchema.Tool>>> toolsChangeConsumers,
|
||||
List<Consumer<List<McpSchema.Resource>>> resourcesChangeConsumers,
|
||||
List<Consumer<List<McpSchema.Prompt>>> promptsChangeConsumers,
|
||||
List<Consumer<McpSchema.LoggingMessageNotification>> loggingConsumers,
|
||||
Function<McpSchema.CreateMessageRequest, McpSchema.CreateMessageResult> samplingHandler) {
|
||||
Function<McpSchema.CreateMessageRequest, McpSchema.CreateMessageResult> samplingHandler,
|
||||
Function<McpSchema.ElicitRequest, McpSchema.ElicitResult> elicitationHandler) {
|
||||
|
||||
/**
|
||||
* Create an instance and validate the arguments.
|
||||
|
|
@ -174,20 +187,23 @@ class McpClientFeatures {
|
|||
* @param promptsChangeConsumers the prompts change consumers.
|
||||
* @param loggingConsumers the logging consumers.
|
||||
* @param samplingHandler the sampling handler.
|
||||
* @param elicitationHandler the elicitation handler.
|
||||
*/
|
||||
public Sync(McpSchema.Implementation clientInfo, McpSchema.ClientCapabilities clientCapabilities,
|
||||
Map<String, McpSchema.Root> roots, List<Consumer<List<McpSchema.Tool>>> toolsChangeConsumers,
|
||||
List<Consumer<List<McpSchema.Resource>>> resourcesChangeConsumers,
|
||||
List<Consumer<List<McpSchema.Prompt>>> promptsChangeConsumers,
|
||||
List<Consumer<McpSchema.LoggingMessageNotification>> loggingConsumers,
|
||||
Function<McpSchema.CreateMessageRequest, McpSchema.CreateMessageResult> samplingHandler) {
|
||||
Function<McpSchema.CreateMessageRequest, McpSchema.CreateMessageResult> samplingHandler,
|
||||
Function<McpSchema.ElicitRequest, McpSchema.ElicitResult> elicitationHandler) {
|
||||
|
||||
Assert.notNull(clientInfo, "Client info must not be null");
|
||||
this.clientInfo = clientInfo;
|
||||
this.clientCapabilities = (clientCapabilities != null) ? clientCapabilities
|
||||
: new McpSchema.ClientCapabilities(null,
|
||||
!Utils.isEmpty(roots) ? new McpSchema.ClientCapabilities.RootCapabilities(false) : null,
|
||||
samplingHandler != null ? new McpSchema.ClientCapabilities.Sampling() : null);
|
||||
samplingHandler != null ? new McpSchema.ClientCapabilities.Sampling() : null,
|
||||
elicitationHandler != null ? new McpSchema.ClientCapabilities.Elicitation() : null);
|
||||
this.roots = roots != null ? new HashMap<>(roots) : new HashMap<>();
|
||||
|
||||
this.toolsChangeConsumers = toolsChangeConsumers != null ? toolsChangeConsumers : List.of();
|
||||
|
|
@ -195,6 +211,7 @@ class McpClientFeatures {
|
|||
this.promptsChangeConsumers = promptsChangeConsumers != null ? promptsChangeConsumers : List.of();
|
||||
this.loggingConsumers = loggingConsumers != null ? loggingConsumers : List.of();
|
||||
this.samplingHandler = samplingHandler;
|
||||
this.elicitationHandler = elicitationHandler;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -36,6 +36,9 @@ public class McpAsyncServerExchange {
|
|||
private static final TypeReference<McpSchema.ListRootsResult> LIST_ROOTS_RESULT_TYPE_REF = new TypeReference<>() {
|
||||
};
|
||||
|
||||
private static final TypeReference<McpSchema.ElicitResult> ELICITATION_RESULT_TYPE_REF = new TypeReference<>() {
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a new asynchronous exchange with the client.
|
||||
* @param session The server session representing a 1-1 interaction.
|
||||
|
|
@ -93,6 +96,31 @@ public class McpAsyncServerExchange {
|
|||
CREATE_MESSAGE_RESULT_TYPE_REF);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new elicitation. MCP provides a standardized way for servers to request
|
||||
* additional information from users through the client during interactions. This flow
|
||||
* allows clients to maintain control over user interactions and data sharing while
|
||||
* enabling servers to gather necessary information dynamically. Servers can request
|
||||
* structured data from users with optional JSON schemas to validate responses.
|
||||
* @param elicitRequest The request to create a new elicitation
|
||||
* @return A Mono that completes when the elicitation has been resolved.
|
||||
* @see McpSchema.ElicitRequest
|
||||
* @see McpSchema.ElicitResult
|
||||
* @see <a href=
|
||||
* "https://spec.modelcontextprotocol.io/specification/client/elicitation/">Elicitation
|
||||
* Specification</a>
|
||||
*/
|
||||
public Mono<McpSchema.ElicitResult> createElicitation(McpSchema.ElicitRequest elicitRequest) {
|
||||
if (this.clientCapabilities == null) {
|
||||
return Mono.error(new McpError("Client must be initialized. Call the initialize method first!"));
|
||||
}
|
||||
if (this.clientCapabilities.elicitation() == null) {
|
||||
return Mono.error(new McpError("Client must be configured with elicitation capabilities"));
|
||||
}
|
||||
return this.session.sendRequest(McpSchema.METHOD_ELICITATION_CREATE, elicitRequest,
|
||||
ELICITATION_RESULT_TYPE_REF);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the list of all roots provided by the client.
|
||||
* @return A Mono that emits the list of roots result.
|
||||
|
|
|
|||
|
|
@ -64,6 +64,24 @@ public class McpSyncServerExchange {
|
|||
return this.exchange.createMessage(createMessageRequest).block();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new elicitation. MCP provides a standardized way for servers to request
|
||||
* additional information from users through the client during interactions. This flow
|
||||
* allows clients to maintain control over user interactions and data sharing while
|
||||
* enabling servers to gather necessary information dynamically. Servers can request
|
||||
* structured data from users with optional JSON schemas to validate responses.
|
||||
* @param elicitRequest The request to create a new elicitation
|
||||
* @return A result containing the elicitation response.
|
||||
* @see McpSchema.ElicitRequest
|
||||
* @see McpSchema.ElicitResult
|
||||
* @see <a href=
|
||||
* "https://spec.modelcontextprotocol.io/specification/client/elicitation/">Elicitation
|
||||
* Specification</a>
|
||||
*/
|
||||
public McpSchema.ElicitResult createElicitation(McpSchema.ElicitRequest elicitRequest) {
|
||||
return this.exchange.createElicitation(elicitRequest).block();
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the list of all roots provided by the client.
|
||||
* @return The list of roots result.
|
||||
|
|
|
|||
|
|
@ -94,6 +94,9 @@ public final class McpSchema {
|
|||
// Sampling Methods
|
||||
public static final String METHOD_SAMPLING_CREATE_MESSAGE = "sampling/createMessage";
|
||||
|
||||
// Elicitation Methods
|
||||
public static final String METHOD_ELICITATION_CREATE = "elicitation/create";
|
||||
|
||||
private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
|
||||
|
||||
// ---------------------------
|
||||
|
|
@ -131,8 +134,8 @@ public final class McpSchema {
|
|||
|
||||
}
|
||||
|
||||
public sealed interface Request
|
||||
permits InitializeRequest, CallToolRequest, CreateMessageRequest, CompleteRequest, GetPromptRequest {
|
||||
public sealed interface Request permits InitializeRequest, CallToolRequest, CreateMessageRequest, ElicitRequest,
|
||||
CompleteRequest, GetPromptRequest {
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -221,7 +224,7 @@ public final class McpSchema {
|
|||
public record InitializeRequest( // @formatter:off
|
||||
@JsonProperty("protocolVersion") String protocolVersion,
|
||||
@JsonProperty("capabilities") ClientCapabilities capabilities,
|
||||
@JsonProperty("clientInfo") Implementation clientInfo) implements Request {
|
||||
@JsonProperty("clientInfo") Implementation clientInfo) implements Request {
|
||||
} // @formatter:on
|
||||
|
||||
@JsonInclude(JsonInclude.Include.NON_ABSENT)
|
||||
|
|
@ -245,6 +248,8 @@ public final class McpSchema {
|
|||
* access to.
|
||||
* @param sampling Provides a standardized way for servers to request LLM sampling
|
||||
* (“completions” or “generations”) from language models via clients.
|
||||
* @param elicitation Provides a standardized way for servers to request additional
|
||||
* information from users through the client during interactions.
|
||||
*
|
||||
*/
|
||||
@JsonInclude(JsonInclude.Include.NON_ABSENT)
|
||||
|
|
@ -252,7 +257,8 @@ public final class McpSchema {
|
|||
public record ClientCapabilities( // @formatter:off
|
||||
@JsonProperty("experimental") Map<String, Object> experimental,
|
||||
@JsonProperty("roots") RootCapabilities roots,
|
||||
@JsonProperty("sampling") Sampling sampling) {
|
||||
@JsonProperty("sampling") Sampling sampling,
|
||||
@JsonProperty("elicitation") Elicitation elicitation) {
|
||||
|
||||
/**
|
||||
* Roots define the boundaries of where servers can operate within the filesystem,
|
||||
|
|
@ -264,7 +270,7 @@ public final class McpSchema {
|
|||
* has changed since the last time the server checked.
|
||||
*/
|
||||
@JsonInclude(JsonInclude.Include.NON_ABSENT)
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public record RootCapabilities(
|
||||
@JsonProperty("listChanged") Boolean listChanged) {
|
||||
}
|
||||
|
|
@ -279,10 +285,22 @@ public final class McpSchema {
|
|||
* image-based interactions and optionally include context
|
||||
* from MCP servers in their prompts.
|
||||
*/
|
||||
@JsonInclude(JsonInclude.Include.NON_ABSENT)
|
||||
@JsonInclude(JsonInclude.Include.NON_ABSENT)
|
||||
public record Sampling() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides a standardized way for servers to request additional
|
||||
* information from users through the client during interactions.
|
||||
* This flow allows clients to maintain control over user
|
||||
* interactions and data sharing while enabling servers to gather
|
||||
* necessary information dynamically. Servers can request structured
|
||||
* data from users with optional JSON schemas to validate responses.
|
||||
*/
|
||||
@JsonInclude(JsonInclude.Include.NON_ABSENT)
|
||||
public record Elicitation() {
|
||||
}
|
||||
|
||||
public static Builder builder() {
|
||||
return new Builder();
|
||||
}
|
||||
|
|
@ -291,6 +309,7 @@ public final class McpSchema {
|
|||
private Map<String, Object> experimental;
|
||||
private RootCapabilities roots;
|
||||
private Sampling sampling;
|
||||
private Elicitation elicitation;
|
||||
|
||||
public Builder experimental(Map<String, Object> experimental) {
|
||||
this.experimental = experimental;
|
||||
|
|
@ -307,8 +326,13 @@ public final class McpSchema {
|
|||
return this;
|
||||
}
|
||||
|
||||
public Builder elicitation() {
|
||||
this.elicitation = new Elicitation();
|
||||
return this;
|
||||
}
|
||||
|
||||
public ClientCapabilities build() {
|
||||
return new ClientCapabilities(experimental, roots, sampling);
|
||||
return new ClientCapabilities(experimental, roots, sampling, elicitation);
|
||||
}
|
||||
}
|
||||
}// @formatter:on
|
||||
|
|
@ -326,11 +350,11 @@ public final class McpSchema {
|
|||
@JsonInclude(JsonInclude.Include.NON_ABSENT)
|
||||
public record CompletionCapabilities() {
|
||||
}
|
||||
|
||||
|
||||
@JsonInclude(JsonInclude.Include.NON_ABSENT)
|
||||
public record LoggingCapabilities() {
|
||||
}
|
||||
|
||||
|
||||
@JsonInclude(JsonInclude.Include.NON_ABSENT)
|
||||
public record PromptCapabilities(
|
||||
@JsonProperty("listChanged") Boolean listChanged) {
|
||||
|
|
@ -727,11 +751,11 @@ public final class McpSchema {
|
|||
@JsonProperty("name") String name,
|
||||
@JsonProperty("description") String description,
|
||||
@JsonProperty("inputSchema") JsonSchema inputSchema) {
|
||||
|
||||
|
||||
public Tool(String name, String description, String schema) {
|
||||
this(name, description, parseSchema(schema));
|
||||
}
|
||||
|
||||
|
||||
} // @formatter:on
|
||||
|
||||
private static JsonSchema parseSchema(String schema) {
|
||||
|
|
@ -758,7 +782,7 @@ public final class McpSchema {
|
|||
@JsonProperty("arguments") Map<String, Object> arguments) implements Request {
|
||||
|
||||
public CallToolRequest(String name, String jsonArguments) {
|
||||
this(name, parseJsonArguments(jsonArguments));
|
||||
this(name, parseJsonArguments(jsonArguments));
|
||||
}
|
||||
|
||||
private static Map<String, Object> parseJsonArguments(String jsonArguments) {
|
||||
|
|
@ -893,7 +917,7 @@ public final class McpSchema {
|
|||
@JsonProperty("costPriority") Double costPriority,
|
||||
@JsonProperty("speedPriority") Double speedPriority,
|
||||
@JsonProperty("intelligencePriority") Double intelligencePriority) {
|
||||
|
||||
|
||||
public static Builder builder() {
|
||||
return new Builder();
|
||||
}
|
||||
|
|
@ -963,7 +987,7 @@ public final class McpSchema {
|
|||
@JsonProperty("includeContext") ContextInclusionStrategy includeContext,
|
||||
@JsonProperty("temperature") Double temperature,
|
||||
@JsonProperty("maxTokens") int maxTokens,
|
||||
@JsonProperty("stopSequences") List<String> stopSequences,
|
||||
@JsonProperty("stopSequences") List<String> stopSequences,
|
||||
@JsonProperty("metadata") Map<String, Object> metadata) implements Request {
|
||||
|
||||
public enum ContextInclusionStrategy {
|
||||
|
|
@ -971,7 +995,7 @@ public final class McpSchema {
|
|||
@JsonProperty("thisServer") THIS_SERVER,
|
||||
@JsonProperty("allServers") ALL_SERVERS
|
||||
}
|
||||
|
||||
|
||||
public static Builder builder() {
|
||||
return new Builder();
|
||||
}
|
||||
|
|
@ -1040,7 +1064,7 @@ public final class McpSchema {
|
|||
@JsonProperty("content") Content content,
|
||||
@JsonProperty("model") String model,
|
||||
@JsonProperty("stopReason") StopReason stopReason) {
|
||||
|
||||
|
||||
public enum StopReason {
|
||||
@JsonProperty("endTurn") END_TURN,
|
||||
@JsonProperty("stopSequence") STOP_SEQUENCE,
|
||||
|
|
@ -1088,6 +1112,79 @@ public final class McpSchema {
|
|||
}
|
||||
}// @formatter:on
|
||||
|
||||
// Elicitation
|
||||
/**
|
||||
* Used by the server to send an elicitation to the client.
|
||||
*
|
||||
* @param message The body of the elicitation message.
|
||||
* @param requestedSchema The elicitation response schema that must be satisfied.
|
||||
*/
|
||||
@JsonInclude(JsonInclude.Include.NON_ABSENT)
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public record ElicitRequest(// @formatter:off
|
||||
@JsonProperty("message") String message,
|
||||
@JsonProperty("requestedSchema") Map<String, Object> requestedSchema) implements Request {
|
||||
|
||||
public static Builder builder() {
|
||||
return new Builder();
|
||||
}
|
||||
|
||||
public static class Builder {
|
||||
private String message;
|
||||
private Map<String, Object> requestedSchema;
|
||||
|
||||
public Builder message(String message) {
|
||||
this.message = message;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder requestedSchema(Map<String, Object> requestedSchema) {
|
||||
this.requestedSchema = requestedSchema;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ElicitRequest build() {
|
||||
return new ElicitRequest(message, requestedSchema);
|
||||
}
|
||||
}
|
||||
}// @formatter:on
|
||||
|
||||
@JsonInclude(JsonInclude.Include.NON_ABSENT)
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public record ElicitResult(// @formatter:off
|
||||
@JsonProperty("action") Action action,
|
||||
@JsonProperty("content") Map<String, Object> content) {
|
||||
|
||||
public enum Action {
|
||||
@JsonProperty("accept") ACCEPT,
|
||||
@JsonProperty("decline") DECLINE,
|
||||
@JsonProperty("cancel") CANCEL
|
||||
}
|
||||
|
||||
public static Builder builder() {
|
||||
return new Builder();
|
||||
}
|
||||
|
||||
public static class Builder {
|
||||
private Action action;
|
||||
private Map<String, Object> content;
|
||||
|
||||
public Builder message(Action action) {
|
||||
this.action = action;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder content(Map<String, Object> content) {
|
||||
this.content = content;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ElicitResult build() {
|
||||
return new ElicitResult(action, content);
|
||||
}
|
||||
}
|
||||
}// @formatter:on
|
||||
|
||||
// ---------------------------
|
||||
// Pagination Interfaces
|
||||
// ---------------------------
|
||||
|
|
|
|||
Loading…
Reference in a new issue