- The McpSyncServer wraps an async server. By default, reactive operations are scheduled on a bounded-elastic scheduler, to offload blocking work and prevent accidental blocking of non-blocking operations. - With the default behavior, there will be thead ops, even in a blocking context, which means thread-locals from the request thread will be lost. This is inconenvient for frameworks that store state in thread-locals. - This commit adds the ability to avoid offloading, when the user is sure they are executing code in a blocking environment. Work happens in the calling thread, and thread-locals are available throughout the execution.
506 lines
22 KiB
Java
506 lines
22 KiB
Java
/*
|
|
* Copyright 2024-2025 the original author or authors.
|
|
*/
|
|
|
|
package io.modelcontextprotocol.server;
|
|
|
|
import java.util.ArrayList;
|
|
import java.util.HashMap;
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
import java.util.function.BiConsumer;
|
|
import java.util.function.BiFunction;
|
|
|
|
import io.modelcontextprotocol.spec.McpSchema;
|
|
import io.modelcontextprotocol.util.Assert;
|
|
import io.modelcontextprotocol.util.Utils;
|
|
import reactor.core.publisher.Mono;
|
|
import reactor.core.scheduler.Schedulers;
|
|
|
|
/**
|
|
* MCP server features specification that a particular server can choose to support.
|
|
*
|
|
* @author Dariusz Jędrzejczyk
|
|
* @author Jihoon Kim
|
|
*/
|
|
public class McpServerFeatures {
|
|
|
|
/**
|
|
* Asynchronous server features specification.
|
|
*
|
|
* @param serverInfo The server implementation details
|
|
* @param serverCapabilities The server capabilities
|
|
* @param tools The list of tool specifications
|
|
* @param resources The map of resource specifications
|
|
* @param resourceTemplates The list of resource templates
|
|
* @param prompts The map of prompt specifications
|
|
* @param rootsChangeConsumers The list of consumers that will be notified when the
|
|
* roots list changes
|
|
* @param instructions The server instructions text
|
|
*/
|
|
record Async(McpSchema.Implementation serverInfo, McpSchema.ServerCapabilities serverCapabilities,
|
|
List<McpServerFeatures.AsyncToolSpecification> tools, Map<String, AsyncResourceSpecification> resources,
|
|
List<McpSchema.ResourceTemplate> resourceTemplates,
|
|
Map<String, McpServerFeatures.AsyncPromptSpecification> prompts,
|
|
Map<McpSchema.CompleteReference, McpServerFeatures.AsyncCompletionSpecification> completions,
|
|
List<BiFunction<McpAsyncServerExchange, List<McpSchema.Root>, Mono<Void>>> rootsChangeConsumers,
|
|
String instructions) {
|
|
|
|
/**
|
|
* Create an instance and validate the arguments.
|
|
* @param serverInfo The server implementation details
|
|
* @param serverCapabilities The server capabilities
|
|
* @param tools The list of tool specifications
|
|
* @param resources The map of resource specifications
|
|
* @param resourceTemplates The list of resource templates
|
|
* @param prompts The map of prompt specifications
|
|
* @param rootsChangeConsumers The list of consumers that will be notified when
|
|
* the roots list changes
|
|
* @param instructions The server instructions text
|
|
*/
|
|
Async(McpSchema.Implementation serverInfo, McpSchema.ServerCapabilities serverCapabilities,
|
|
List<McpServerFeatures.AsyncToolSpecification> tools, Map<String, AsyncResourceSpecification> resources,
|
|
List<McpSchema.ResourceTemplate> resourceTemplates,
|
|
Map<String, McpServerFeatures.AsyncPromptSpecification> prompts,
|
|
Map<McpSchema.CompleteReference, McpServerFeatures.AsyncCompletionSpecification> completions,
|
|
List<BiFunction<McpAsyncServerExchange, List<McpSchema.Root>, Mono<Void>>> rootsChangeConsumers,
|
|
String instructions) {
|
|
|
|
Assert.notNull(serverInfo, "Server info must not be null");
|
|
|
|
this.serverInfo = serverInfo;
|
|
this.serverCapabilities = (serverCapabilities != null) ? serverCapabilities
|
|
: new McpSchema.ServerCapabilities(null, // completions
|
|
null, // experimental
|
|
new McpSchema.ServerCapabilities.LoggingCapabilities(), // Enable
|
|
// logging
|
|
// by
|
|
// default
|
|
!Utils.isEmpty(prompts) ? new McpSchema.ServerCapabilities.PromptCapabilities(false) : null,
|
|
!Utils.isEmpty(resources)
|
|
? new McpSchema.ServerCapabilities.ResourceCapabilities(false, false) : null,
|
|
!Utils.isEmpty(tools) ? new McpSchema.ServerCapabilities.ToolCapabilities(false) : null);
|
|
|
|
this.tools = (tools != null) ? tools : List.of();
|
|
this.resources = (resources != null) ? resources : Map.of();
|
|
this.resourceTemplates = (resourceTemplates != null) ? resourceTemplates : List.of();
|
|
this.prompts = (prompts != null) ? prompts : Map.of();
|
|
this.completions = (completions != null) ? completions : Map.of();
|
|
this.rootsChangeConsumers = (rootsChangeConsumers != null) ? rootsChangeConsumers : List.of();
|
|
this.instructions = instructions;
|
|
}
|
|
|
|
/**
|
|
* Convert a synchronous specification into an asynchronous one and provide
|
|
* blocking code offloading to prevent accidental blocking of the non-blocking
|
|
* transport.
|
|
* @param syncSpec a potentially blocking, synchronous specification.
|
|
* @param immediateExecution when true, do not offload. Do NOT set to true when
|
|
* using a non-blocking transport.
|
|
* @return a specification which is protected from blocking calls specified by the
|
|
* user.
|
|
*/
|
|
static Async fromSync(Sync syncSpec, boolean immediateExecution) {
|
|
List<McpServerFeatures.AsyncToolSpecification> tools = new ArrayList<>();
|
|
for (var tool : syncSpec.tools()) {
|
|
tools.add(AsyncToolSpecification.fromSync(tool, immediateExecution));
|
|
}
|
|
|
|
Map<String, AsyncResourceSpecification> resources = new HashMap<>();
|
|
syncSpec.resources().forEach((key, resource) -> {
|
|
resources.put(key, AsyncResourceSpecification.fromSync(resource, immediateExecution));
|
|
});
|
|
|
|
Map<String, AsyncPromptSpecification> prompts = new HashMap<>();
|
|
syncSpec.prompts().forEach((key, prompt) -> {
|
|
prompts.put(key, AsyncPromptSpecification.fromSync(prompt, immediateExecution));
|
|
});
|
|
|
|
Map<McpSchema.CompleteReference, McpServerFeatures.AsyncCompletionSpecification> completions = new HashMap<>();
|
|
syncSpec.completions().forEach((key, completion) -> {
|
|
completions.put(key, AsyncCompletionSpecification.fromSync(completion, immediateExecution));
|
|
});
|
|
|
|
List<BiFunction<McpAsyncServerExchange, List<McpSchema.Root>, Mono<Void>>> rootChangeConsumers = new ArrayList<>();
|
|
|
|
for (var rootChangeConsumer : syncSpec.rootsChangeConsumers()) {
|
|
rootChangeConsumers.add((exchange, list) -> Mono
|
|
.<Void>fromRunnable(() -> rootChangeConsumer.accept(new McpSyncServerExchange(exchange), list))
|
|
.subscribeOn(Schedulers.boundedElastic()));
|
|
}
|
|
|
|
return new Async(syncSpec.serverInfo(), syncSpec.serverCapabilities(), tools, resources,
|
|
syncSpec.resourceTemplates(), prompts, completions, rootChangeConsumers, syncSpec.instructions());
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Synchronous server features specification.
|
|
*
|
|
* @param serverInfo The server implementation details
|
|
* @param serverCapabilities The server capabilities
|
|
* @param tools The list of tool specifications
|
|
* @param resources The map of resource specifications
|
|
* @param resourceTemplates The list of resource templates
|
|
* @param prompts The map of prompt specifications
|
|
* @param rootsChangeConsumers The list of consumers that will be notified when the
|
|
* roots list changes
|
|
* @param instructions The server instructions text
|
|
*/
|
|
record Sync(McpSchema.Implementation serverInfo, McpSchema.ServerCapabilities serverCapabilities,
|
|
List<McpServerFeatures.SyncToolSpecification> tools,
|
|
Map<String, McpServerFeatures.SyncResourceSpecification> resources,
|
|
List<McpSchema.ResourceTemplate> resourceTemplates,
|
|
Map<String, McpServerFeatures.SyncPromptSpecification> prompts,
|
|
Map<McpSchema.CompleteReference, McpServerFeatures.SyncCompletionSpecification> completions,
|
|
List<BiConsumer<McpSyncServerExchange, List<McpSchema.Root>>> rootsChangeConsumers, String instructions) {
|
|
|
|
/**
|
|
* Create an instance and validate the arguments.
|
|
* @param serverInfo The server implementation details
|
|
* @param serverCapabilities The server capabilities
|
|
* @param tools The list of tool specifications
|
|
* @param resources The map of resource specifications
|
|
* @param resourceTemplates The list of resource templates
|
|
* @param prompts The map of prompt specifications
|
|
* @param rootsChangeConsumers The list of consumers that will be notified when
|
|
* the roots list changes
|
|
* @param instructions The server instructions text
|
|
*/
|
|
Sync(McpSchema.Implementation serverInfo, McpSchema.ServerCapabilities serverCapabilities,
|
|
List<McpServerFeatures.SyncToolSpecification> tools,
|
|
Map<String, McpServerFeatures.SyncResourceSpecification> resources,
|
|
List<McpSchema.ResourceTemplate> resourceTemplates,
|
|
Map<String, McpServerFeatures.SyncPromptSpecification> prompts,
|
|
Map<McpSchema.CompleteReference, McpServerFeatures.SyncCompletionSpecification> completions,
|
|
List<BiConsumer<McpSyncServerExchange, List<McpSchema.Root>>> rootsChangeConsumers,
|
|
String instructions) {
|
|
|
|
Assert.notNull(serverInfo, "Server info must not be null");
|
|
|
|
this.serverInfo = serverInfo;
|
|
this.serverCapabilities = (serverCapabilities != null) ? serverCapabilities
|
|
: new McpSchema.ServerCapabilities(null, // completions
|
|
null, // experimental
|
|
new McpSchema.ServerCapabilities.LoggingCapabilities(), // Enable
|
|
// logging
|
|
// by
|
|
// default
|
|
!Utils.isEmpty(prompts) ? new McpSchema.ServerCapabilities.PromptCapabilities(false) : null,
|
|
!Utils.isEmpty(resources)
|
|
? new McpSchema.ServerCapabilities.ResourceCapabilities(false, false) : null,
|
|
!Utils.isEmpty(tools) ? new McpSchema.ServerCapabilities.ToolCapabilities(false) : null);
|
|
|
|
this.tools = (tools != null) ? tools : new ArrayList<>();
|
|
this.resources = (resources != null) ? resources : new HashMap<>();
|
|
this.resourceTemplates = (resourceTemplates != null) ? resourceTemplates : new ArrayList<>();
|
|
this.prompts = (prompts != null) ? prompts : new HashMap<>();
|
|
this.completions = (completions != null) ? completions : new HashMap<>();
|
|
this.rootsChangeConsumers = (rootsChangeConsumers != null) ? rootsChangeConsumers : new ArrayList<>();
|
|
this.instructions = instructions;
|
|
}
|
|
|
|
}
|
|
|
|
/**
|
|
* Specification of a tool with its asynchronous handler function. Tools are the
|
|
* primary way for MCP servers to expose functionality to AI models. Each tool
|
|
* represents a specific capability, such as:
|
|
* <ul>
|
|
* <li>Performing calculations
|
|
* <li>Accessing external APIs
|
|
* <li>Querying databases
|
|
* <li>Manipulating files
|
|
* <li>Executing system commands
|
|
* </ul>
|
|
*
|
|
* <p>
|
|
* Example tool specification: <pre>{@code
|
|
* new McpServerFeatures.AsyncToolSpecification(
|
|
* new Tool(
|
|
* "calculator",
|
|
* "Performs mathematical calculations",
|
|
* new JsonSchemaObject()
|
|
* .required("expression")
|
|
* .property("expression", JsonSchemaType.STRING)
|
|
* ),
|
|
* (exchange, args) -> {
|
|
* String expr = (String) args.get("expression");
|
|
* return Mono.fromSupplier(() -> evaluate(expr))
|
|
* .map(result -> new CallToolResult("Result: " + result));
|
|
* }
|
|
* )
|
|
* }</pre>
|
|
*
|
|
* @param tool The tool definition including name, description, and parameter schema
|
|
* @param call The function that implements the tool's logic, receiving arguments and
|
|
* returning results. The function's first argument is an
|
|
* {@link McpAsyncServerExchange} upon which the server can interact with the
|
|
* connected client. The second arguments is a map of tool arguments.
|
|
*/
|
|
public record AsyncToolSpecification(McpSchema.Tool tool,
|
|
BiFunction<McpAsyncServerExchange, Map<String, Object>, Mono<McpSchema.CallToolResult>> call) {
|
|
|
|
static AsyncToolSpecification fromSync(SyncToolSpecification tool, boolean immediate) {
|
|
// FIXME: This is temporary, proper validation should be implemented
|
|
if (tool == null) {
|
|
return null;
|
|
}
|
|
return new AsyncToolSpecification(tool.tool(), (exchange, map) -> {
|
|
var toolResult = Mono.fromCallable(() -> tool.call().apply(new McpSyncServerExchange(exchange), map));
|
|
return immediate ? toolResult : toolResult.subscribeOn(Schedulers.boundedElastic());
|
|
});
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Specification of a resource with its asynchronous handler function. Resources
|
|
* provide context to AI models by exposing data such as:
|
|
* <ul>
|
|
* <li>File contents
|
|
* <li>Database records
|
|
* <li>API responses
|
|
* <li>System information
|
|
* <li>Application state
|
|
* </ul>
|
|
*
|
|
* <p>
|
|
* Example resource specification: <pre>{@code
|
|
* new McpServerFeatures.AsyncResourceSpecification(
|
|
* new Resource("docs", "Documentation files", "text/markdown"),
|
|
* (exchange, request) ->
|
|
* Mono.fromSupplier(() -> readFile(request.getPath()))
|
|
* .map(ReadResourceResult::new)
|
|
* )
|
|
* }</pre>
|
|
*
|
|
* @param resource The resource definition including name, description, and MIME type
|
|
* @param readHandler The function that handles resource read requests. The function's
|
|
* first argument is an {@link McpAsyncServerExchange} upon which the server can
|
|
* interact with the connected client. The second arguments is a
|
|
* {@link io.modelcontextprotocol.spec.McpSchema.ReadResourceRequest}.
|
|
*/
|
|
public record AsyncResourceSpecification(McpSchema.Resource resource,
|
|
BiFunction<McpAsyncServerExchange, McpSchema.ReadResourceRequest, Mono<McpSchema.ReadResourceResult>> readHandler) {
|
|
|
|
static AsyncResourceSpecification fromSync(SyncResourceSpecification resource, boolean immediateExecution) {
|
|
// FIXME: This is temporary, proper validation should be implemented
|
|
if (resource == null) {
|
|
return null;
|
|
}
|
|
return new AsyncResourceSpecification(resource.resource(), (exchange, req) -> {
|
|
var resourceResult = Mono
|
|
.fromCallable(() -> resource.readHandler().apply(new McpSyncServerExchange(exchange), req));
|
|
return immediateExecution ? resourceResult : resourceResult.subscribeOn(Schedulers.boundedElastic());
|
|
});
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Specification of a prompt template with its asynchronous handler function. Prompts
|
|
* provide structured templates for AI model interactions, supporting:
|
|
* <ul>
|
|
* <li>Consistent message formatting
|
|
* <li>Parameter substitution
|
|
* <li>Context injection
|
|
* <li>Response formatting
|
|
* <li>Instruction templating
|
|
* </ul>
|
|
*
|
|
* <p>
|
|
* Example prompt specification: <pre>{@code
|
|
* new McpServerFeatures.AsyncPromptSpecification(
|
|
* new Prompt("analyze", "Code analysis template"),
|
|
* (exchange, request) -> {
|
|
* String code = request.getArguments().get("code");
|
|
* return Mono.just(new GetPromptResult(
|
|
* "Analyze this code:\n\n" + code + "\n\nProvide feedback on:"
|
|
* ));
|
|
* }
|
|
* )
|
|
* }</pre>
|
|
*
|
|
* @param prompt The prompt definition including name and description
|
|
* @param promptHandler The function that processes prompt requests and returns
|
|
* formatted templates. The function's first argument is an
|
|
* {@link McpAsyncServerExchange} upon which the server can interact with the
|
|
* connected client. The second arguments is a
|
|
* {@link io.modelcontextprotocol.spec.McpSchema.GetPromptRequest}.
|
|
*/
|
|
public record AsyncPromptSpecification(McpSchema.Prompt prompt,
|
|
BiFunction<McpAsyncServerExchange, McpSchema.GetPromptRequest, Mono<McpSchema.GetPromptResult>> promptHandler) {
|
|
|
|
static AsyncPromptSpecification fromSync(SyncPromptSpecification prompt, boolean immediateExecution) {
|
|
// FIXME: This is temporary, proper validation should be implemented
|
|
if (prompt == null) {
|
|
return null;
|
|
}
|
|
return new AsyncPromptSpecification(prompt.prompt(), (exchange, req) -> {
|
|
var promptResult = Mono
|
|
.fromCallable(() -> prompt.promptHandler().apply(new McpSyncServerExchange(exchange), req));
|
|
return immediateExecution ? promptResult : promptResult.subscribeOn(Schedulers.boundedElastic());
|
|
});
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Specification of a completion handler function with asynchronous execution support.
|
|
* Completions generate AI model outputs based on prompt or resource references and
|
|
* user-provided arguments. This abstraction enables:
|
|
* <ul>
|
|
* <li>Customizable response generation logic
|
|
* <li>Parameter-driven template expansion
|
|
* <li>Dynamic interaction with connected clients
|
|
* </ul>
|
|
*
|
|
* @param referenceKey The unique key representing the completion reference.
|
|
* @param completionHandler The asynchronous function that processes completion
|
|
* requests and returns results. The first argument is an
|
|
* {@link McpAsyncServerExchange} used to interact with the client. The second
|
|
* argument is a {@link io.modelcontextprotocol.spec.McpSchema.CompleteRequest}.
|
|
*/
|
|
public record AsyncCompletionSpecification(McpSchema.CompleteReference referenceKey,
|
|
BiFunction<McpAsyncServerExchange, McpSchema.CompleteRequest, Mono<McpSchema.CompleteResult>> completionHandler) {
|
|
|
|
/**
|
|
* Converts a synchronous {@link SyncCompletionSpecification} into an
|
|
* {@link AsyncCompletionSpecification} by wrapping the handler in a bounded
|
|
* elastic scheduler for safe non-blocking execution.
|
|
* @param completion the synchronous completion specification
|
|
* @return an asynchronous wrapper of the provided sync specification, or
|
|
* {@code null} if input is null
|
|
*/
|
|
static AsyncCompletionSpecification fromSync(SyncCompletionSpecification completion,
|
|
boolean immediateExecution) {
|
|
if (completion == null) {
|
|
return null;
|
|
}
|
|
return new AsyncCompletionSpecification(completion.referenceKey(), (exchange, request) -> {
|
|
var completionResult = Mono.fromCallable(
|
|
() -> completion.completionHandler().apply(new McpSyncServerExchange(exchange), request));
|
|
return immediateExecution ? completionResult
|
|
: completionResult.subscribeOn(Schedulers.boundedElastic());
|
|
});
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Specification of a tool with its synchronous handler function. Tools are the
|
|
* primary way for MCP servers to expose functionality to AI models. Each tool
|
|
* represents a specific capability, such as:
|
|
* <ul>
|
|
* <li>Performing calculations
|
|
* <li>Accessing external APIs
|
|
* <li>Querying databases
|
|
* <li>Manipulating files
|
|
* <li>Executing system commands
|
|
* </ul>
|
|
*
|
|
* <p>
|
|
* Example tool specification: <pre>{@code
|
|
* new McpServerFeatures.SyncToolSpecification(
|
|
* new Tool(
|
|
* "calculator",
|
|
* "Performs mathematical calculations",
|
|
* new JsonSchemaObject()
|
|
* .required("expression")
|
|
* .property("expression", JsonSchemaType.STRING)
|
|
* ),
|
|
* (exchange, args) -> {
|
|
* String expr = (String) args.get("expression");
|
|
* return new CallToolResult("Result: " + evaluate(expr));
|
|
* }
|
|
* )
|
|
* }</pre>
|
|
*
|
|
* @param tool The tool definition including name, description, and parameter schema
|
|
* @param call The function that implements the tool's logic, receiving arguments and
|
|
* returning results. The function's first argument is an
|
|
* {@link McpSyncServerExchange} upon which the server can interact with the connected
|
|
* client. The second arguments is a map of arguments passed to the tool.
|
|
*/
|
|
public record SyncToolSpecification(McpSchema.Tool tool,
|
|
BiFunction<McpSyncServerExchange, Map<String, Object>, McpSchema.CallToolResult> call) {
|
|
}
|
|
|
|
/**
|
|
* Specification of a resource with its synchronous handler function. Resources
|
|
* provide context to AI models by exposing data such as:
|
|
* <ul>
|
|
* <li>File contents
|
|
* <li>Database records
|
|
* <li>API responses
|
|
* <li>System information
|
|
* <li>Application state
|
|
* </ul>
|
|
*
|
|
* <p>
|
|
* Example resource specification: <pre>{@code
|
|
* new McpServerFeatures.SyncResourceSpecification(
|
|
* new Resource("docs", "Documentation files", "text/markdown"),
|
|
* (exchange, request) -> {
|
|
* String content = readFile(request.getPath());
|
|
* return new ReadResourceResult(content);
|
|
* }
|
|
* )
|
|
* }</pre>
|
|
*
|
|
* @param resource The resource definition including name, description, and MIME type
|
|
* @param readHandler The function that handles resource read requests. The function's
|
|
* first argument is an {@link McpSyncServerExchange} upon which the server can
|
|
* interact with the connected client. The second arguments is a
|
|
* {@link io.modelcontextprotocol.spec.McpSchema.ReadResourceRequest}.
|
|
*/
|
|
public record SyncResourceSpecification(McpSchema.Resource resource,
|
|
BiFunction<McpSyncServerExchange, McpSchema.ReadResourceRequest, McpSchema.ReadResourceResult> readHandler) {
|
|
}
|
|
|
|
/**
|
|
* Specification of a prompt template with its synchronous handler function. Prompts
|
|
* provide structured templates for AI model interactions, supporting:
|
|
* <ul>
|
|
* <li>Consistent message formatting
|
|
* <li>Parameter substitution
|
|
* <li>Context injection
|
|
* <li>Response formatting
|
|
* <li>Instruction templating
|
|
* </ul>
|
|
*
|
|
* <p>
|
|
* Example prompt specification: <pre>{@code
|
|
* new McpServerFeatures.SyncPromptSpecification(
|
|
* new Prompt("analyze", "Code analysis template"),
|
|
* (exchange, request) -> {
|
|
* String code = request.getArguments().get("code");
|
|
* return new GetPromptResult(
|
|
* "Analyze this code:\n\n" + code + "\n\nProvide feedback on:"
|
|
* );
|
|
* }
|
|
* )
|
|
* }</pre>
|
|
*
|
|
* @param prompt The prompt definition including name and description
|
|
* @param promptHandler The function that processes prompt requests and returns
|
|
* formatted templates. The function's first argument is an
|
|
* {@link McpSyncServerExchange} upon which the server can interact with the connected
|
|
* client. The second arguments is a
|
|
* {@link io.modelcontextprotocol.spec.McpSchema.GetPromptRequest}.
|
|
*/
|
|
public record SyncPromptSpecification(McpSchema.Prompt prompt,
|
|
BiFunction<McpSyncServerExchange, McpSchema.GetPromptRequest, McpSchema.GetPromptResult> promptHandler) {
|
|
}
|
|
|
|
/**
|
|
* Specification of a completion handler function with synchronous execution support.
|
|
*
|
|
* @param referenceKey The unique key representing the completion reference.
|
|
* @param completionHandler The synchronous function that processes completion
|
|
* requests and returns results. The first argument is an
|
|
* {@link McpSyncServerExchange} used to interact with the client. The second argument
|
|
* is a {@link io.modelcontextprotocol.spec.McpSchema.CompleteRequest}.
|
|
*/
|
|
public record SyncCompletionSpecification(McpSchema.CompleteReference referenceKey,
|
|
BiFunction<McpSyncServerExchange, McpSchema.CompleteRequest, McpSchema.CompleteResult> completionHandler) {
|
|
}
|
|
|
|
}
|