Remove temporary delegate impl from McpAsyncServer

Signed-off-by: Dariusz Jędrzejczyk <dariusz.jedrzejczyk@broadcom.com>
This commit is contained in:
Dariusz Jędrzejczyk 2025-05-09 12:57:36 +02:00 • committed by Christian Tzolov
commit 0069c977ef

View file

@ -82,178 +82,6 @@ public class McpAsyncServer {
private static final Logger logger = LoggerFactory.getLogger(McpAsyncServer.class); private static final Logger logger = LoggerFactory.getLogger(McpAsyncServer.class);
private final McpAsyncServer delegate;
McpAsyncServer() {
this.delegate = null;
}
/**
* Create a new McpAsyncServer with the given transport provider and capabilities.
* @param mcpTransportProvider The transport layer implementation for MCP
* communication.
* @param features The MCP server supported features.
* @param objectMapper The ObjectMapper to use for JSON serialization/deserialization
*/
McpAsyncServer(McpServerTransportProvider mcpTransportProvider, ObjectMapper objectMapper,
McpServerFeatures.Async features, Duration requestTimeout,
McpUriTemplateManagerFactory uriTemplateManagerFactory) {
this.delegate = new AsyncServerImpl(mcpTransportProvider, objectMapper, requestTimeout, features,
uriTemplateManagerFactory);
}
/**
* Get the server capabilities that define the supported features and functionality.
* @return The server capabilities
*/
public McpSchema.ServerCapabilities getServerCapabilities() {
return this.delegate.getServerCapabilities();
}
/**
* Get the server implementation information.
* @return The server implementation details
*/
public McpSchema.Implementation getServerInfo() {
return this.delegate.getServerInfo();
}
/**
* Gracefully closes the server, allowing any in-progress operations to complete.
* @return A Mono that completes when the server has been closed
*/
public Mono<Void> closeGracefully() {
return this.delegate.closeGracefully();
}
/**
* Close the server immediately.
*/
public void close() {
this.delegate.close();
}
// ---------------------------------------
// Tool Management
// ---------------------------------------
/**
* Add a new tool specification at runtime.
* @param toolSpecification The tool specification to add
* @return Mono that completes when clients have been notified of the change
*/
public Mono<Void> addTool(McpServerFeatures.AsyncToolSpecification toolSpecification) {
return this.delegate.addTool(toolSpecification);
}
/**
* Remove a tool handler at runtime.
* @param toolName The name of the tool handler to remove
* @return Mono that completes when clients have been notified of the change
*/
public Mono<Void> removeTool(String toolName) {
return this.delegate.removeTool(toolName);
}
/**
* Notifies clients that the list of available tools has changed.
* @return A Mono that completes when all clients have been notified
*/
public Mono<Void> notifyToolsListChanged() {
return this.delegate.notifyToolsListChanged();
}
// ---------------------------------------
// Resource Management
// ---------------------------------------
/**
* Add a new resource handler at runtime.
* @param resourceHandler The resource handler to add
* @return Mono that completes when clients have been notified of the change
*/
public Mono<Void> addResource(McpServerFeatures.AsyncResourceSpecification resourceHandler) {
return this.delegate.addResource(resourceHandler);
}
/**
* Remove a resource handler at runtime.
* @param resourceUri The URI of the resource handler to remove
* @return Mono that completes when clients have been notified of the change
*/
public Mono<Void> removeResource(String resourceUri) {
return this.delegate.removeResource(resourceUri);
}
/**
* Notifies clients that the list of available resources has changed.
* @return A Mono that completes when all clients have been notified
*/
public Mono<Void> notifyResourcesListChanged() {
return this.delegate.notifyResourcesListChanged();
}
// ---------------------------------------
// Prompt Management
// ---------------------------------------
/**
* Add a new prompt handler at runtime.
* @param promptSpecification The prompt handler to add
* @return Mono that completes when clients have been notified of the change
*/
public Mono<Void> addPrompt(McpServerFeatures.AsyncPromptSpecification promptSpecification) {
return this.delegate.addPrompt(promptSpecification);
}
/**
* Remove a prompt handler at runtime.
* @param promptName The name of the prompt handler to remove
* @return Mono that completes when clients have been notified of the change
*/
public Mono<Void> removePrompt(String promptName) {
return this.delegate.removePrompt(promptName);
}
/**
* Notifies clients that the list of available prompts has changed.
* @return A Mono that completes when all clients have been notified
*/
public Mono<Void> notifyPromptsListChanged() {
return this.delegate.notifyPromptsListChanged();
}
// ---------------------------------------
// Logging Management
// ---------------------------------------
/**
* This implementation would, incorrectly, broadcast the logging message to all
* connected clients, using a single minLoggingLevel for all of them. Similar to the
* sampling and roots, the logging level should be set per client session and use the
* ServerExchange to send the logging message to the right client.
* @param loggingMessageNotification The logging message to send
* @return A Mono that completes when the notification has been sent
* @deprecated Use
* {@link McpAsyncServerExchange#loggingNotification(LoggingMessageNotification)}
* instead.
*/
@Deprecated
public Mono<Void> loggingNotification(LoggingMessageNotification loggingMessageNotification) {
return this.delegate.loggingNotification(loggingMessageNotification);
}
// ---------------------------------------
// Sampling
// ---------------------------------------
/**
* This method is package-private and used for test only. Should not be called by user
* code.
* @param protocolVersions the Client supported protocol versions.
*/
void setProtocolVersions(List<String> protocolVersions) {
this.delegate.setProtocolVersions(protocolVersions);
}
private static class AsyncServerImpl extends McpAsyncServer {
private final McpServerTransportProvider mcpTransportProvider; private final McpServerTransportProvider mcpTransportProvider;
private final ObjectMapper objectMapper; private final ObjectMapper objectMapper;
@ -282,8 +110,15 @@ public class McpAsyncServer {
private McpUriTemplateManagerFactory uriTemplateManagerFactory = new DeafaultMcpUriTemplateManagerFactory(); private McpUriTemplateManagerFactory uriTemplateManagerFactory = new DeafaultMcpUriTemplateManagerFactory();
AsyncServerImpl(McpServerTransportProvider mcpTransportProvider, ObjectMapper objectMapper, /**
Duration requestTimeout, McpServerFeatures.Async features, * Create a new McpAsyncServer with the given transport provider and capabilities.
* @param mcpTransportProvider The transport layer implementation for MCP
* communication.
* @param features The MCP server supported features.
* @param objectMapper The ObjectMapper to use for JSON serialization/deserialization
*/
McpAsyncServer(McpServerTransportProvider mcpTransportProvider, ObjectMapper objectMapper,
McpServerFeatures.Async features, Duration requestTimeout,
McpUriTemplateManagerFactory uriTemplateManagerFactory) { McpUriTemplateManagerFactory uriTemplateManagerFactory) {
this.mcpTransportProvider = mcpTransportProvider; this.mcpTransportProvider = mcpTransportProvider;
this.objectMapper = objectMapper; this.objectMapper = objectMapper;
@ -341,10 +176,8 @@ public class McpAsyncServer {
.rootsChangeConsumers(); .rootsChangeConsumers();
if (Utils.isEmpty(rootsChangeConsumers)) { if (Utils.isEmpty(rootsChangeConsumers)) {
rootsChangeConsumers = List.of((exchange, rootsChangeConsumers = List.of((exchange, roots) -> Mono.fromRunnable(() -> logger
roots) -> Mono.fromRunnable(() -> logger.warn( .warn("Roots list changed notification, but no consumers provided. Roots list changed: {}", roots)));
"Roots list changed notification, but no consumers provided. Roots list changed: {}",
roots)));
} }
notificationHandlers.put(McpSchema.METHOD_NOTIFICATION_ROOTS_LIST_CHANGED, notificationHandlers.put(McpSchema.METHOD_NOTIFICATION_ROOTS_LIST_CHANGED,
@ -387,20 +220,33 @@ public class McpAsyncServer {
}); });
} }
/**
* Get the server capabilities that define the supported features and functionality.
* @return The server capabilities
*/
public McpSchema.ServerCapabilities getServerCapabilities() { public McpSchema.ServerCapabilities getServerCapabilities() {
return this.serverCapabilities; return this.serverCapabilities;
} }
/**
* Get the server implementation information.
* @return The server implementation details
*/
public McpSchema.Implementation getServerInfo() { public McpSchema.Implementation getServerInfo() {
return this.serverInfo; return this.serverInfo;
} }
@Override /**
* Gracefully closes the server, allowing any in-progress operations to complete.
* @return A Mono that completes when the server has been closed
*/
public Mono<Void> closeGracefully() { public Mono<Void> closeGracefully() {
return this.mcpTransportProvider.closeGracefully(); return this.mcpTransportProvider.closeGracefully();
} }
@Override /**
* Close the server immediately.
*/
public void close() { public void close() {
this.mcpTransportProvider.close(); this.mcpTransportProvider.close();
} }
@ -421,7 +267,11 @@ public class McpAsyncServer {
// Tool Management // Tool Management
// --------------------------------------- // ---------------------------------------
@Override /**
* Add a new tool specification at runtime.
* @param toolSpecification The tool specification to add
* @return Mono that completes when clients have been notified of the change
*/
public Mono<Void> addTool(McpServerFeatures.AsyncToolSpecification toolSpecification) { public Mono<Void> addTool(McpServerFeatures.AsyncToolSpecification toolSpecification) {
if (toolSpecification == null) { if (toolSpecification == null) {
return Mono.error(new McpError("Tool specification must not be null")); return Mono.error(new McpError("Tool specification must not be null"));
@ -453,7 +303,11 @@ public class McpAsyncServer {
}); });
} }
@Override /**
* Remove a tool handler at runtime.
* @param toolName The name of the tool handler to remove
* @return Mono that completes when clients have been notified of the change
*/
public Mono<Void> removeTool(String toolName) { public Mono<Void> removeTool(String toolName) {
if (toolName == null) { if (toolName == null) {
return Mono.error(new McpError("Tool name must not be null")); return Mono.error(new McpError("Tool name must not be null"));
@ -476,7 +330,10 @@ public class McpAsyncServer {
}); });
} }
@Override /**
* Notifies clients that the list of available tools has changed.
* @return A Mono that completes when all clients have been notified
*/
public Mono<Void> notifyToolsListChanged() { public Mono<Void> notifyToolsListChanged() {
return this.mcpTransportProvider.notifyClients(McpSchema.METHOD_NOTIFICATION_TOOLS_LIST_CHANGED, null); return this.mcpTransportProvider.notifyClients(McpSchema.METHOD_NOTIFICATION_TOOLS_LIST_CHANGED, null);
} }
@ -512,7 +369,11 @@ public class McpAsyncServer {
// Resource Management // Resource Management
// --------------------------------------- // ---------------------------------------
@Override /**
* Add a new resource handler at runtime.
* @param resourceSpecification The resource handler to add
* @return Mono that completes when clients have been notified of the change
*/
public Mono<Void> addResource(McpServerFeatures.AsyncResourceSpecification resourceSpecification) { public Mono<Void> addResource(McpServerFeatures.AsyncResourceSpecification resourceSpecification) {
if (resourceSpecification == null || resourceSpecification.resource() == null) { if (resourceSpecification == null || resourceSpecification.resource() == null) {
return Mono.error(new McpError("Resource must not be null")); return Mono.error(new McpError("Resource must not be null"));
@ -535,7 +396,11 @@ public class McpAsyncServer {
}); });
} }
@Override /**
* Remove a resource handler at runtime.
* @param resourceUri The URI of the resource handler to remove
* @return Mono that completes when clients have been notified of the change
*/
public Mono<Void> removeResource(String resourceUri) { public Mono<Void> removeResource(String resourceUri) {
if (resourceUri == null) { if (resourceUri == null) {
return Mono.error(new McpError("Resource URI must not be null")); return Mono.error(new McpError("Resource URI must not be null"));
@ -557,7 +422,10 @@ public class McpAsyncServer {
}); });
} }
@Override /**
* Notifies clients that the list of available resources has changed.
* @return A Mono that completes when all clients have been notified
*/
public Mono<Void> notifyResourcesListChanged() { public Mono<Void> notifyResourcesListChanged() {
return this.mcpTransportProvider.notifyClients(McpSchema.METHOD_NOTIFICATION_RESOURCES_LIST_CHANGED, null); return this.mcpTransportProvider.notifyClients(McpSchema.METHOD_NOTIFICATION_RESOURCES_LIST_CHANGED, null);
} }
@ -585,8 +453,8 @@ public class McpAsyncServer {
.filter(uri -> uri.contains("{")) .filter(uri -> uri.contains("{"))
.map(uri -> { .map(uri -> {
var resource = this.resources.get(uri).resource(); var resource = this.resources.get(uri).resource();
var template = new McpSchema.ResourceTemplate(resource.uri(), resource.name(), var template = new McpSchema.ResourceTemplate(resource.uri(), resource.name(), resource.description(),
resource.description(), resource.mimeType(), resource.annotations()); resource.mimeType(), resource.annotations());
return template; return template;
}) })
.toList(); .toList();
@ -619,7 +487,11 @@ public class McpAsyncServer {
// Prompt Management // Prompt Management
// --------------------------------------- // ---------------------------------------
@Override /**
* Add a new prompt handler at runtime.
* @param promptSpecification The prompt handler to add
* @return Mono that completes when clients have been notified of the change
*/
public Mono<Void> addPrompt(McpServerFeatures.AsyncPromptSpecification promptSpecification) { public Mono<Void> addPrompt(McpServerFeatures.AsyncPromptSpecification promptSpecification) {
if (promptSpecification == null) { if (promptSpecification == null) {
return Mono.error(new McpError("Prompt specification must not be null")); return Mono.error(new McpError("Prompt specification must not be null"));
@ -632,8 +504,8 @@ public class McpAsyncServer {
McpServerFeatures.AsyncPromptSpecification specification = this.prompts McpServerFeatures.AsyncPromptSpecification specification = this.prompts
.putIfAbsent(promptSpecification.prompt().name(), promptSpecification); .putIfAbsent(promptSpecification.prompt().name(), promptSpecification);
if (specification != null) { if (specification != null) {
return Mono.error(new McpError( return Mono.error(
"Prompt with name '" + promptSpecification.prompt().name() + "' already exists")); new McpError("Prompt with name '" + promptSpecification.prompt().name() + "' already exists"));
} }
logger.debug("Added prompt handler: {}", promptSpecification.prompt().name()); logger.debug("Added prompt handler: {}", promptSpecification.prompt().name());
@ -648,7 +520,11 @@ public class McpAsyncServer {
}); });
} }
@Override /**
* Remove a prompt handler at runtime.
* @param promptName The name of the prompt handler to remove
* @return Mono that completes when clients have been notified of the change
*/
public Mono<Void> removePrompt(String promptName) { public Mono<Void> removePrompt(String promptName) {
if (promptName == null) { if (promptName == null) {
return Mono.error(new McpError("Prompt name must not be null")); return Mono.error(new McpError("Prompt name must not be null"));
@ -673,7 +549,10 @@ public class McpAsyncServer {
}); });
} }
@Override /**
* Notifies clients that the list of available prompts has changed.
* @return A Mono that completes when all clients have been notified
*/
public Mono<Void> notifyPromptsListChanged() { public Mono<Void> notifyPromptsListChanged() {
return this.mcpTransportProvider.notifyClients(McpSchema.METHOD_NOTIFICATION_PROMPTS_LIST_CHANGED, null); return this.mcpTransportProvider.notifyClients(McpSchema.METHOD_NOTIFICATION_PROMPTS_LIST_CHANGED, null);
} }
@ -714,7 +593,18 @@ public class McpAsyncServer {
// Logging Management // Logging Management
// --------------------------------------- // ---------------------------------------
@Override /**
* This implementation would, incorrectly, broadcast the logging message to all
* connected clients, using a single minLoggingLevel for all of them. Similar to the
* sampling and roots, the logging level should be set per client session and use the
* ServerExchange to send the logging message to the right client.
* @param loggingMessageNotification The logging message to send
* @return A Mono that completes when the notification has been sent
* @deprecated Use
* {@link McpAsyncServerExchange#loggingNotification(LoggingMessageNotification)}
* instead.
*/
@Deprecated
public Mono<Void> loggingNotification(LoggingMessageNotification loggingMessageNotification) { public Mono<Void> loggingNotification(LoggingMessageNotification loggingMessageNotification) {
if (loggingMessageNotification == null) { if (loggingMessageNotification == null) {
@ -781,10 +671,8 @@ public class McpAsyncServer {
} }
} }
if (type.equals("ref/resource") if (type.equals("ref/resource") && request.ref() instanceof McpSchema.ResourceReference resourceReference) {
&& request.ref() instanceof McpSchema.ResourceReference resourceReference) { McpServerFeatures.AsyncResourceSpecification resourceSpec = this.resources.get(resourceReference.uri());
McpServerFeatures.AsyncResourceSpecification resourceSpec = this.resources
.get(resourceReference.uri());
if (resourceSpec == null) { if (resourceSpec == null) {
return Mono.error(new McpError("Resource not found: " + resourceReference.uri())); return Mono.error(new McpError("Resource not found: " + resourceReference.uri()));
} }
@ -807,16 +695,16 @@ public class McpAsyncServer {
} }
/** /**
* Parses the raw JSON-RPC request parameters into a * Parses the raw JSON-RPC request parameters into a {@link McpSchema.CompleteRequest}
* {@link McpSchema.CompleteRequest} object. * object.
* <p> * <p>
* This method manually extracts the `ref` and `argument` fields from the input * This method manually extracts the `ref` and `argument` fields from the input map,
* map, determines the correct reference type (either prompt or resource), and * determines the correct reference type (either prompt or resource), and constructs a
* constructs a fully-typed {@code CompleteRequest} instance. * fully-typed {@code CompleteRequest} instance.
* @param object the raw request parameters, expected to be a Map containing "ref" * @param object the raw request parameters, expected to be a Map containing "ref" and
* and "argument" entries. * "argument" entries.
* @return a {@link McpSchema.CompleteRequest} representing the structured * @return a {@link McpSchema.CompleteRequest} representing the structured completion
* completion request. * request.
* @throws IllegalArgumentException if the "ref" type is not recognized. * @throws IllegalArgumentException if the "ref" type is not recognized.
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@ -835,21 +723,19 @@ public class McpAsyncServer {
String argName = (String) argMap.get("name"); String argName = (String) argMap.get("name");
String argValue = (String) argMap.get("value"); String argValue = (String) argMap.get("value");
McpSchema.CompleteRequest.CompleteArgument argument = new McpSchema.CompleteRequest.CompleteArgument( McpSchema.CompleteRequest.CompleteArgument argument = new McpSchema.CompleteRequest.CompleteArgument(argName,
argName, argValue); argValue);
return new McpSchema.CompleteRequest(ref, argument); return new McpSchema.CompleteRequest(ref, argument);
} }
// --------------------------------------- /**
// Sampling * This method is package-private and used for test only. Should not be called by user
// --------------------------------------- * code.
* @param protocolVersions the Client supported protocol versions.
@Override */
void setProtocolVersions(List<String> protocolVersions) { void setProtocolVersions(List<String> protocolVersions) {
this.protocolVersions = protocolVersions; this.protocolVersions = protocolVersions;
} }
} }
}