docs(mcp) Improve McpServer and McpClient javadoc

This commit is contained in:
Christian Tzolov 2024-12-30 13:13:32 +01:00
commit c36d4677c1
2 changed files with 484 additions and 91 deletions

View file

@ -34,42 +34,90 @@ import org.springframework.ai.mcp.spec.McpTransport;
import org.springframework.ai.mcp.util.Assert;
/**
* Factory class providing static methods for creating Model Context Protocol (MCP)
* clients. This class serves as the main entry point for establishing connections with
* MCP servers, offering both synchronous and asynchronous client implementations.
*
* <p>
* The class provides factory methods to create either:
* Factory class for creating Model Context Protocol (MCP) clients. MCP is a protocol that enables
* AI models to interact with external tools and resources through a standardized interface.
*
* <p>This class serves as the main entry point for establishing connections with MCP servers,
* implementing the client-side of the MCP specification. The protocol follows a client-server
* architecture where:
* <ul>
* <li>{@link McpAsyncClient} for non-blocking operations
* <li>{@link McpSyncClient} for blocking operations
* <li>The client (this implementation) initiates connections and sends requests
* <li>The server responds to requests and provides access to tools and resources
* <li>Communication occurs through a transport layer (e.g., stdio, SSE) using JSON-RPC 2.0
* </ul>
*
* <p>
* Use the builder pattern for flexible client configuration:
* <p>The class provides factory methods to create either:
* <ul>
* <li>{@link McpAsyncClient} for non-blocking operations with CompletableFuture responses
* <li>{@link McpSyncClient} for blocking operations with direct responses
* </ul>
*
* <p>Example of creating a basic client:
* <pre>{@code
* McpClient.using(transport)
* .requestTimeout(Duration.ofSeconds(5))
* .sync(); // or .async()
* .requestTimeout(Duration.ofSeconds(5))
* .sync(); // or .async()
* }</pre>
*
* <p>Example with advanced configuration:
* <pre>{@code
* McpClient.using(transport)
* .requestTimeout(Duration.ofSeconds(10))
* .capabilities(new ClientCapabilities(...))
* .clientInfo(new Implementation("My Client", "1.0.0"))
* .roots(new Root("file://workspace", "Workspace Files"))
* .toolsChangeConsumer(tools -> System.out.println("Tools updated: " + tools))
* .async();
* }</pre>
*
* <p>The client supports:
* <ul>
* <li>Tool discovery and invocation
* <li>Resource access and management
* <li>Prompt template handling
* <li>Real-time updates through change consumers
* <li>Custom sampling strategies
* </ul>
*
* @author Christian Tzolov
* @author Dariusz Jędrzejczyk
* @see McpAsyncClient
* @see McpSyncClient
* @see McpTransport
*/
public interface McpClient {
/**
* Start building an MCP client with the specified transport.
* @param transport The transport layer implementation for MCP communication
* @return A new builder instance
* Start building an MCP client with the specified transport layer.
* The transport layer handles the low-level communication between
* client and server using protocols like stdio or Server-Sent Events (SSE).
*
* @param transport The transport layer implementation for MCP communication.
* Common implementations include {@code StdioClientTransport}
* for stdio-based communication and {@code SseClientTransport}
* for SSE-based communication.
* @return A new builder instance for configuring the client
* @throws IllegalArgumentException if transport is null
*/
public static Builder using(McpTransport transport) {
return new Builder(transport);
}
/**
* Builder class for creating MCP clients with custom configuration.
* Builder class for creating and configuring MCP clients. This class follows
* the builder pattern to provide a fluent API for setting up clients with
* custom configurations.
*
* <p>The builder supports configuration of:
* <ul>
* <li>Transport layer for client-server communication
* <li>Request timeouts for operation boundaries
* <li>Client capabilities for feature negotiation
* <li>Client implementation details for version tracking
* <li>Root URIs for resource access
* <li>Change notification handlers for tools, resources, and prompts
* <li>Custom message sampling logic
* </ul>
*/
public static class Builder {
@ -79,7 +127,7 @@ public interface McpClient {
private ClientCapabilities capabilities;
private Implementation clientInfo = new Implementation("Spring AI MCP Client", "0.3.0");
private Implementation clientInfo = new Implementation("Spring AI MCP Client", "0.3.1");
private Map<String, Root> roots = new HashMap<>();
@ -97,9 +145,14 @@ public interface McpClient {
}
/**
* Set the request timeout duration.
* @param requestTimeout The duration to wait before timing out requests
* @return This builder instance
* Sets the duration to wait for server responses before timing out requests.
* This timeout applies to all requests made through the client, including
* tool calls, resource access, and prompt operations.
*
* @param requestTimeout The duration to wait before timing out requests.
* Must not be null.
* @return This builder instance for method chaining
* @throws IllegalArgumentException if requestTimeout is null
*/
public Builder requestTimeout(Duration requestTimeout) {
Assert.notNull(requestTimeout, "Request timeout must not be null");
@ -107,18 +160,46 @@ public interface McpClient {
return this;
}
/**
* Sets the client capabilities that will be advertised to the server during
* connection initialization. Capabilities define what features the client supports,
* such as tool execution, resource access, and prompt handling.
*
* @param capabilities The client capabilities configuration. Must not be null.
* @return This builder instance for method chaining
* @throws IllegalArgumentException if capabilities is null
*/
public Builder capabilities(ClientCapabilities capabilities) {
Assert.notNull(capabilities, "Capabilities must not be null");
this.capabilities = capabilities;
return this;
}
/**
* Sets the client implementation information that will be shared with the server
* during connection initialization. This helps with version compatibility and
* debugging.
*
* @param clientInfo The client implementation details including name and version.
* Must not be null.
* @return This builder instance for method chaining
* @throws IllegalArgumentException if clientInfo is null
*/
public Builder clientInfo(Implementation clientInfo) {
Assert.notNull(clientInfo, "Client info must not be null");
this.clientInfo = clientInfo;
return this;
}
/**
* Sets the root URIs that this client can access. Roots define the base URIs
* for resources that the client can request from the server. For example,
* a root might be "file://workspace" for accessing workspace files.
*
* @param roots A list of root definitions. Must not be null.
* @return This builder instance for method chaining
* @throws IllegalArgumentException if roots is null
*/
public Builder roots(List<Root> roots) {
Assert.notNull(roots, "Roots must not be null");
for (Root root : roots) {
@ -127,6 +208,15 @@ public interface McpClient {
return this;
}
/**
* Sets the root URIs that this client can access, using a varargs parameter
* for convenience. This is an alternative to {@link #roots(List)}.
*
* @param roots An array of root definitions. Must not be null.
* @return This builder instance for method chaining
* @throws IllegalArgumentException if roots is null
* @see #roots(List)
*/
public Builder roots(Root... roots) {
Assert.notNull(roots, "Roots must not be null");
for (Root root : roots) {
@ -135,24 +225,64 @@ public interface McpClient {
return this;
}
/**
* Sets a custom sampling handler for processing message creation requests.
* The sampling handler can modify or validate messages before they are sent
* to the server, enabling custom processing logic.
*
* @param samplingHandler A function that processes message requests and returns
* results. Must not be null.
* @return This builder instance for method chaining
* @throws IllegalArgumentException if samplingHandler is null
*/
public Builder sampling(Function<CreateMessageRequest, CreateMessageResult> samplingHandler) {
Assert.notNull(samplingHandler, "Sampling handler must not be null");
this.samplingHandler = samplingHandler;
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 being added or removed.
*
* @param toolsChangeConsumer A consumer that receives the updated list of
* available tools. Must not be null.
* @return This builder instance for method chaining
* @throws IllegalArgumentException if toolsChangeConsumer is null
*/
public Builder toolsChangeConsumer(Consumer<List<McpSchema.Tool>> toolsChangeConsumer) {
Assert.notNull(toolsChangeConsumer, "Tools change consumer must not be null");
this.toolsChangeConsumers.add(toolsChangeConsumer);
return this;
}
/**
* Adds a consumer to be notified when the available resources change. This allows
* the client to react to changes in the server's resource availability, such as
* files being added or removed.
*
* @param resourcesChangeConsumer A consumer that receives the updated list of
* available resources. Must not be null.
* @return This builder instance for method chaining
* @throws IllegalArgumentException if resourcesChangeConsumer is null
*/
public Builder resourcesChangeConsumer(Consumer<List<McpSchema.Resource>> resourcesChangeConsumer) {
Assert.notNull(resourcesChangeConsumer, "Resources change consumer must not be null");
this.resourcesChangeConsumers.add(resourcesChangeConsumer);
return this;
}
/**
* Adds a consumer to be notified when the available prompts change. This allows
* the client to react to changes in the server's prompt templates, such as
* new templates being added or existing ones being modified.
*
* @param promptsChangeConsumer A consumer that receives the updated list of
* available prompts. Must not be null.
* @return This builder instance for method chaining
* @throws IllegalArgumentException if promptsChangeConsumer is null
*/
public Builder promptsChangeConsumer(Consumer<List<McpSchema.Prompt>> promptsChangeConsumer) {
Assert.notNull(promptsChangeConsumer, "Prompts change consumer must not be null");
this.promptsChangeConsumers.add(promptsChangeConsumer);
@ -160,16 +290,25 @@ public interface McpClient {
}
/**
* Build a synchronous MCP client.
* @return A new instance of {@link McpSyncClient}
* Builds a synchronous MCP client that provides blocking operations.
* Synchronous clients wait for each operation to complete before returning,
* making them simpler to use but potentially less performant for
* concurrent operations.
*
* @return A new instance of {@link McpSyncClient} configured with this
* builder's settings
*/
public McpSyncClient sync() {
return new McpSyncClient(async());
}
/**
* Build an asynchronous MCP client.
* @return A new instance of {@link McpAsyncClient}
* Builds an asynchronous MCP client that provides non-blocking operations.
* Asynchronous clients return CompletableFuture objects immediately,
* allowing for concurrent operations and reactive programming patterns.
*
* @return A new instance of {@link McpAsyncClient} configured with this
* builder's settings
*/
public McpAsyncClient async() {
return new McpAsyncClient(transport, requestTimeout, clientInfo, capabilities, roots, toolsChangeConsumers,

View file

@ -30,49 +30,162 @@ import org.springframework.ai.mcp.spec.McpTransport;
import org.springframework.ai.mcp.util.Assert;
/**
* Factory class providing static methods for creating Model Context Protocol (MCP)
* servers. This class serves as the main entry point for establishing MCP servers,
* offering both synchronous and asynchronous server implementations.
* Factory class for creating Model Context Protocol (MCP) servers. MCP servers expose
* tools, resources, and prompts to AI models through a standardized interface.
*
* <p>
* The class provides factory methods to create either:
* <p>This class serves as the main entry point for implementing the server-side of
* the MCP specification. The server's responsibilities include:
* <ul>
* <li>{@link McpAsyncServer} for non-blocking operations
* <li>{@link McpSyncServer} for blocking operations
* <li>Exposing tools that models can invoke to perform actions
* <li>Providing access to resources that give models context
* <li>Managing prompt templates for structured model interactions
* <li>Handling client connections and requests
* <li>Implementing capability negotiation
* </ul>
*
* <p>
* Use the builder pattern for flexible server configuration:
* <p>The class provides factory methods to create either:
* <ul>
* <li>{@link McpAsyncServer} for non-blocking operations with CompletableFuture responses
* <li>{@link McpSyncServer} for blocking operations with direct responses
* </ul>
*
* <p>Example of creating a basic server:
* <pre>{@code
* McpServer.using(transport)
* .serverInfo(new McpSchema.Implementation("my-server", "1.0.0"))
* .tool(new MyToolHandler())
* .async(); // or .sync()
* .info("my-server", "1.0.0")
* .tool(new Tool("calculator", "Performs calculations", schema),
* args -> new CallToolResult("Result: " + calculate(args)))
* .sync(); // or .async()
* }</pre>
*
* <p>Example with comprehensive configuration:
* <pre>{@code
* McpServer.using(transport)
* .info("advanced-server", "2.0.0")
* .capabilities(new ServerCapabilities(...))
* // Register tools
* .tools(
* new ToolRegistration(calculatorTool, calculatorHandler),
* new ToolRegistration(weatherTool, weatherHandler)
* )
* // Register resources
* .resources(
* new ResourceRegistration(fileResource, fileHandler),
* new ResourceRegistration(dbResource, dbHandler)
* )
* // Add resource templates
* .resourceTemplates(
* new ResourceTemplate("file://{path}", "Access files"),
* new ResourceTemplate("db://{table}", "Access database")
* )
* // Register prompts
* .prompts(
* new PromptRegistration(analysisPrompt, analysisHandler),
* new PromptRegistration(summaryPrompt, summaryHandler)
* )
* .async();
* }</pre>
*
* @author Christian Tzolov
* @see McpAsyncServer
* @see McpSyncServer
* @see McpTransport
*/
public interface McpServer {
/**
* Registration of a tool with its handler function. MCP allows servers to expose
* tools that can be invoked by language models. Tools enable models to interact with
* external systems, such as querying databases, calling APIs, or performing
* computations. Each tool is uniquely identified by a name and includes metadata
* describing its schema.
* Registration of a tool with its 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>
*
* @param tool The tool definition
* @param call The function to handle tool execution
* <p>Example tool registration:
* <pre>{@code
* new ToolRegistration(
* new Tool(
* "calculator",
* "Performs mathematical calculations",
* new JsonSchemaObject()
* .required("expression")
* .property("expression", JsonSchemaType.STRING)
* ),
* 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
*/
public static record ToolRegistration(Tool tool, Function<Map<String, Object>, CallToolResult> call) {
}
/**
* Registration of a resource with its 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 registration:
* <pre>{@code
* new ResourceRegistration(
* new Resource("docs", "Documentation files", "text/markdown"),
* 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
*/
public static record ResourceRegistration(McpSchema.Resource resource,
Function<McpSchema.ReadResourceRequest, McpSchema.ReadResourceResult> readHandler) {
}
/**
* Registration of a prompt template with its 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 registration:
* <pre>{@code
* new PromptRegistration(
* new Prompt("analyze", "Code analysis template"),
* 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
*/
public static record PromptRegistration(McpSchema.Prompt propmpt,
Function<McpSchema.GetPromptRequest, McpSchema.GetPromptResult> promptHandler) {
}
@ -132,9 +245,14 @@ public interface McpServer {
}
/**
* Set the server implementation information.
* @param serverInfo The server implementation details
* @return This builder instance
* Sets the server implementation information that will be shared with clients
* during connection initialization. This helps with version compatibility,
* debugging, and server identification.
*
* @param serverInfo The server implementation details including name and version.
* Must not be null.
* @return This builder instance for method chaining
* @throws IllegalArgumentException if serverInfo is null
*/
public Builder info(McpSchema.Implementation serverInfo) {
Assert.notNull(serverInfo, "Server info must not be null");
@ -143,10 +261,14 @@ public interface McpServer {
}
/**
* Set the server implementation information using name and version.
* @param name The server name
* @param version The server version
* @return This builder instance
* Sets the server implementation information using name and version strings.
* This is a convenience method alternative to {@link #info(McpSchema.Implementation)}.
*
* @param name The server name. Must not be null or empty.
* @param version The server version. Must not be null or empty.
* @return This builder instance for method chaining
* @throws IllegalArgumentException if name or version is null or empty
* @see #info(McpSchema.Implementation)
*/
public Builder info(String name, String version) {
Assert.hasText(name, "Name must not be null or empty");
@ -156,9 +278,20 @@ public interface McpServer {
}
/**
* Set the server capabilities.
* @param serverCapabilities The server capabilities configuration
* @return This builder instance
* Sets the server capabilities that will be advertised to clients during
* connection initialization. Capabilities define what features the server
* supports, such as:
* <ul>
* <li>Tool execution
* <li>Resource access
* <li>Prompt handling
* <li>Streaming responses
* <li>Batch operations
* </ul>
*
* @param serverCapabilities The server capabilities configuration. Must not be null.
* @return This builder instance for method chaining
* @throws IllegalArgumentException if serverCapabilities is null
*/
public Builder capabilities(McpSchema.ServerCapabilities serverCapabilities) {
this.serverCapabilities = serverCapabilities;
@ -166,10 +299,23 @@ public interface McpServer {
}
/**
* Add a tool with its handler function.
* @param tool The tool definition
* @param handler The function to handle tool execution
* @return This builder instance
* Adds a single tool with its implementation handler to the server. This is
* a convenience method for registering individual tools without creating a
* {@link ToolRegistration} explicitly.
*
* <p>Example usage:
* <pre>{@code
* .tool(
* new Tool("calculator", "Performs calculations", schema),
* args -> new CallToolResult("Result: " + calculate(args))
* )
* }</pre>
*
* @param tool The tool definition including name, description, and schema.
* Must not be null.
* @param handler The function that implements the tool's logic. Must not be null.
* @return This builder instance for method chaining
* @throws IllegalArgumentException if tool or handler is null
*/
public Builder tool(McpSchema.Tool tool, Function<Map<String, Object>, McpSchema.CallToolResult> handler) {
Assert.notNull(tool, "Tool must not be null");
@ -181,9 +327,15 @@ public interface McpServer {
}
/**
* Add multiple tool handlers to the server.
* @param toolRegistrations The list of tool handlers to add
* @return This builder instance
* Adds multiple tools with their handlers to the server using a List.
* This method is useful when tools are dynamically generated or loaded
* from a configuration source.
*
* @param toolRegistrations The list of tool registrations to add.
* Must not be null.
* @return This builder instance for method chaining
* @throws IllegalArgumentException if toolRegistrations is null
* @see #tools(ToolRegistration...)
*/
public Builder tools(List<ToolRegistration> toolRegistrations) {
Assert.notNull(toolRegistrations, "Tool handlers list must not be null");
@ -192,9 +344,22 @@ public interface McpServer {
}
/**
* Register tools with the server.
* @param toolRegistrations The map of tools to register
* @return This builder instance
* Adds multiple tools with their handlers to the server using varargs.
* This method provides a convenient way to register multiple tools inline.
*
* <p>Example usage:
* <pre>{@code
* .tools(
* new ToolRegistration(calculatorTool, calculatorHandler),
* new ToolRegistration(weatherTool, weatherHandler),
* new ToolRegistration(fileManagerTool, fileManagerHandler)
* )
* }</pre>
*
* @param toolRegistrations The tool registrations to add. Must not be null.
* @return This builder instance for method chaining
* @throws IllegalArgumentException if toolRegistrations is null
* @see #tools(List)
*/
public Builder tools(ToolRegistration... toolRegistrations) {
for (ToolRegistration tool : toolRegistrations) {
@ -204,9 +369,15 @@ public interface McpServer {
}
/**
* Register resources with the server.
* @param resourceRegsitrations The map of resources to register
* @return This builder instance
* Registers multiple resources with their handlers using a Map.
* This method is useful when resources are dynamically generated
* or loaded from a configuration source.
*
* @param resourceRegsitrations Map of resource name to registration.
* Must not be null.
* @return This builder instance for method chaining
* @throws IllegalArgumentException if resourceRegsitrations is null
* @see #resources(ResourceRegistration...)
*/
public Builder resources(Map<String, ResourceRegistration> resourceRegsitrations) {
Assert.notNull(resourceRegsitrations, "Resource handlers map must not be null");
@ -215,9 +386,15 @@ public interface McpServer {
}
/**
* Register resources with the server.
* @param resourceRegsitrations The list of resources to register
* @return This builder instance
* Registers multiple resources with their handlers using a List.
* This method is useful when resources need to be added in bulk
* from a collection.
*
* @param resourceRegsitrations List of resource registrations.
* Must not be null.
* @return This builder instance for method chaining
* @throws IllegalArgumentException if resourceRegsitrations is null
* @see #resources(ResourceRegistration...)
*/
public Builder resources(List<ResourceRegistration> resourceRegsitrations) {
Assert.notNull(resourceRegsitrations, "Resource handlers list must not be null");
@ -228,9 +405,23 @@ public interface McpServer {
}
/**
* Register resources with the server.
* @param resourceRegistrations The list of resources to register
* @return This builder instance
* Registers multiple resources with their handlers using varargs.
* This method provides a convenient way to register multiple
* resources inline.
*
* <p>Example usage:
* <pre>{@code
* .resources(
* new ResourceRegistration(fileResource, fileHandler),
* new ResourceRegistration(dbResource, dbHandler),
* new ResourceRegistration(apiResource, apiHandler)
* )
* }</pre>
*
* @param resourceRegistrations The resource registrations to add.
* Must not be null.
* @return This builder instance for method chaining
* @throws IllegalArgumentException if resourceRegistrations is null
*/
public Builder resources(ResourceRegistration... resourceRegistrations) {
Assert.notNull(resourceRegistrations, "Resource handlers list must not be null");
@ -241,15 +432,36 @@ public interface McpServer {
}
/**
* Set the resource templates.
* @param resourceTemplates The list of resource templates
* @return This builder instance
* Sets the resource templates that define patterns for dynamic resource
* access. Templates use URI patterns with placeholders that can be
* filled at runtime.
*
* <p>Example usage:
* <pre>{@code
* .resourceTemplates(
* new ResourceTemplate("file://{path}", "Access files by path"),
* new ResourceTemplate("db://{table}/{id}", "Access database records")
* )
* }</pre>
*
* @param resourceTemplates List of resource templates. If null, clears
* existing templates.
* @return This builder instance for method chaining
* @see #resourceTemplates(ResourceTemplate...)
*/
public Builder resourceTemplates(List<ResourceTemplate> resourceTemplates) {
this.resourceTemplates = resourceTemplates;
return this;
}
/**
* Sets the resource templates using varargs for convenience.
* This is an alternative to {@link #resourceTemplates(List)}.
*
* @param resourceTemplates The resource templates to set.
* @return This builder instance for method chaining
* @see #resourceTemplates(List)
*/
public Builder resourceTemplates(ResourceTemplate... resourceTemplates) {
for (ResourceTemplate resourceTemplate : resourceTemplates) {
this.resourceTemplates.add(resourceTemplate);
@ -258,9 +470,23 @@ public interface McpServer {
}
/**
* Register prompts with the server.
* @param prompts The map of prompts to register
* @return This builder instance
* Registers multiple prompts with their handlers using a Map.
* This method is useful when prompts are dynamically generated
* or loaded from a configuration source.
*
* <p>Example usage:
* <pre>{@code
* Map<String, PromptRegistration> prompts = new HashMap<>();
* prompts.put("analysis", new PromptRegistration(
* new Prompt("analysis", "Code analysis template"),
* request -> new GetPromptResult(generateAnalysisPrompt(request))
* ));
* .prompts(prompts)
* }</pre>
*
* @param prompts Map of prompt name to registration. Must not be null.
* @return This builder instance for method chaining
* @throws IllegalArgumentException if prompts is null
*/
public Builder prompts(Map<String, PromptRegistration> prompts) {
this.prompts.putAll(prompts);
@ -268,9 +494,14 @@ public interface McpServer {
}
/**
* Register prompts with the server.
* @param prompts The list of prompts to register
* @return This builder instance.
* Registers multiple prompts with their handlers using a List.
* This method is useful when prompts need to be added in bulk
* from a collection.
*
* @param prompts List of prompt registrations. Must not be null.
* @return This builder instance for method chaining
* @throws IllegalArgumentException if prompts is null
* @see #prompts(PromptRegistration...)
*/
public Builder prompts(List<PromptRegistration> prompts) {
for (PromptRegistration prompt : prompts) {
@ -280,9 +511,22 @@ public interface McpServer {
}
/**
* Register prompts with the server.
* @param prompts The list of prompts to register
* @return This builder instance
* Registers multiple prompts with their handlers using varargs.
* This method provides a convenient way to register multiple
* prompts inline.
*
* <p>Example usage:
* <pre>{@code
* .prompts(
* new PromptRegistration(analysisPrompt, analysisHandler),
* new PromptRegistration(summaryPrompt, summaryHandler),
* new PromptRegistration(reviewPrompt, reviewHandler)
* )
* }</pre>
*
* @param prompts The prompt registrations to add. Must not be null.
* @return This builder instance for method chaining
* @throws IllegalArgumentException if prompts is null
*/
public Builder prompts(PromptRegistration... prompts) {
for (PromptRegistration prompt : prompts) {
@ -292,16 +536,26 @@ public interface McpServer {
}
/**
* Build a synchronous MCP server.
* @return A new instance of {@link McpSyncServer}
* Builds a synchronous MCP server that provides blocking operations.
* Synchronous servers process each request to completion before handling
* the next one, making them simpler to implement but potentially less
* performant for concurrent operations.
*
* @return A new instance of {@link McpSyncServer} configured with this
* builder's settings
*/
public McpSyncServer sync() {
return new McpSyncServer(async());
}
/**
* Build an asynchronous MCP server.
* @return A new instance of {@link McpAsyncServer}
* Builds an asynchronous MCP server that provides non-blocking operations.
* Asynchronous servers can handle multiple requests concurrently using
* CompletableFuture, making them more efficient for high-concurrency
* scenarios but more complex to implement.
*
* @return A new instance of {@link McpAsyncServer} configured with this
* builder's settings
*/
public McpAsyncServer async() {
if (serverInfo == null) {