Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -185,19 +185,6 @@ public static class Builder {
// Default constructor
}

/**
* Creates a new builder with the specified base URI.
* @param baseUri the base URI of the MCP server
* @deprecated Use {@link HttpClientSseClientTransport#builder(String)} instead.
* This constructor is deprecated and will be removed or made {@code protected} or
* {@code private} in a future release.
*/
@Deprecated(forRemoval = true)
public Builder(String baseUri) {
Assert.hasText(baseUri, "baseUri must not be empty");
this.baseUri = baseUri;
}

/**
* Sets the base URI.
* @param baseUri the base URI
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,9 @@ public Mono<McpSchema.JSONRPCResponse> handleRequest(McpTransportContext transpo
McpSchema.JSONRPCRequest request) {
McpStatelessRequestHandler<?> requestHandler = this.requestHandlers.get(request.method());
if (requestHandler == null) {
return Mono.error(new McpError("Missing handler for request type: " + request.method()));
return Mono.error(McpError.builder(McpSchema.ErrorCodes.METHOD_NOT_FOUND)
.message("Missing handler for request type: " + request.method())
.build());
}
return requestHandler.handle(transportContext, request.params())
.map(result -> new McpSchema.JSONRPCResponse(McpSchema.JSONRPC_VERSION, request.id(), result, null))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -326,7 +326,7 @@ public Mono<Void> addTool(McpServerFeatures.AsyncToolSpecification toolSpecifica
if (toolSpecification.tool() == null) {
return Mono.error(new IllegalArgumentException("Tool must not be null"));
}
if (toolSpecification.call() == null && toolSpecification.callHandler() == null) {
if (toolSpecification.callHandler() == null) {
return Mono.error(new IllegalArgumentException("Tool call handler must not be null"));
}
if (this.serverCapabilities.tools() == null) {
Expand Down Expand Up @@ -869,32 +869,6 @@ private McpRequestHandler<McpSchema.GetPromptResult> promptsGetRequestHandler()
// 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) {

if (loggingMessageNotification == null) {
return Mono.error(new McpError("Logging message must not be null"));
}

if (loggingMessageNotification.level().level() < minLoggingLevel.level()) {
return Mono.empty();
}

return this.mcpTransportProvider.notifyClients(McpSchema.METHOD_NOTIFICATION_MESSAGE,
loggingMessageNotification);
}

private McpRequestHandler<Object> setLoggerRequestHandler() {
return (exchange, params) -> {
return Mono.defer(() -> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,28 +49,6 @@ public class McpAsyncServerExchange {
public static final TypeRef<Object> OBJECT_TYPE_REF = new TypeRef<>() {
};

/**
* Create a new asynchronous exchange with the client.
* @param session The server session representing a 1-1 interaction.
* @param clientCapabilities The client capabilities that define the supported
* features and functionality.
* @param clientInfo The client implementation information.
* @deprecated Use
* {@link #McpAsyncServerExchange(String, McpLoggableSession, McpSchema.ClientCapabilities, McpSchema.Implementation, McpTransportContext)}
*/
@Deprecated
public McpAsyncServerExchange(McpSession session, McpSchema.ClientCapabilities clientCapabilities,
McpSchema.Implementation clientInfo) {
this.sessionId = null;
if (!(session instanceof McpLoggableSession)) {
throw new IllegalArgumentException("Expecting session to be a McpLoggableSession instance");
}
this.session = (McpLoggableSession) session;
this.clientCapabilities = clientCapabilities;
this.clientInfo = clientInfo;
this.transportContext = McpTransportContext.EMPTY;
}

/**
* Create a new asynchronous exchange with the client.
* @param session The server session representing a 1-1 interaction.
Expand Down Expand Up @@ -142,10 +120,11 @@ public String sessionId() {
*/
public Mono<McpSchema.CreateMessageResult> createMessage(McpSchema.CreateMessageRequest createMessageRequest) {
if (this.clientCapabilities == null) {
return Mono.error(new McpError("Client must be initialized. Call the initialize method first!"));
return Mono
.error(new IllegalStateException("Client must be initialized. Call the initialize method first!"));
}
if (this.clientCapabilities.sampling() == null) {
return Mono.error(new McpError("Client must be configured with sampling capabilities"));
return Mono.error(new IllegalStateException("Client must be configured with sampling capabilities"));
}
return this.session.sendRequest(McpSchema.METHOD_SAMPLING_CREATE_MESSAGE, createMessageRequest,
CREATE_MESSAGE_RESULT_TYPE_REF);
Expand All @@ -167,10 +146,11 @@ public Mono<McpSchema.CreateMessageResult> createMessage(McpSchema.CreateMessage
*/
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!"));
return Mono
.error(new IllegalStateException("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 Mono.error(new IllegalStateException("Client must be configured with elicitation capabilities"));
}
return this.session.sendRequest(McpSchema.METHOD_ELICITATION_CREATE, elicitRequest,
ELICITATION_RESULT_TYPE_REF);
Expand Down Expand Up @@ -215,7 +195,7 @@ public Mono<McpSchema.ListRootsResult> listRoots(String cursor) {
public Mono<Void> loggingNotification(LoggingMessageNotification loggingMessageNotification) {

if (loggingMessageNotification == null) {
return Mono.error(new McpError("Logging message must not be null"));
return Mono.error(new IllegalStateException("Logging message must not be null"));
}

return Mono.defer(() -> {
Expand All @@ -234,7 +214,7 @@ public Mono<Void> loggingNotification(LoggingMessageNotification loggingMessageN
*/
public Mono<Void> progressNotification(McpSchema.ProgressNotification progressNotification) {
if (progressNotification == null) {
return Mono.error(new McpError("Progress notification must not be null"));
return Mono.error(new IllegalStateException("Progress notification must not be null"));
}
return this.session.sendNotification(McpSchema.METHOD_NOTIFICATION_PROGRESS, progressNotification);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,9 +66,9 @@
* Example of creating a basic synchronous server: <pre>{@code
* McpServer.sync(transportProvider)
* .serverInfo("my-server", "1.0.0")
* .tool(Tool.builder().name("calculator").title("Performs calculations").inputSchema(schema).build(),
* (exchange, args) -> CallToolResult.builder()
* .content(List.of(new McpSchema.TextContent("Result: " + calculate(args))))
* .toolCall(Tool.builder().name("calculator").title("Performs calculations").inputSchema(schema).build(),
* (exchange, request) -> CallToolResult.builder()
* .content(List.of(new McpSchema.TextContent("Result: " + calculate(request.arguments()))))
* .isError(false)
* .build())
* .build();
Expand All @@ -77,8 +77,8 @@
* Example of creating a basic asynchronous server: <pre>{@code
* McpServer.async(transportProvider)
* .serverInfo("my-server", "1.0.0")
* .tool(Tool.builder().name("calculator").title("Performs calculations").inputSchema(schema).build(),
* (exchange, args) -> Mono.fromSupplier(() -> calculate(args))
* .toolCall(Tool.builder().name("calculator").title("Performs calculations").inputSchema(schema).build(),
* (exchange, request) -> Mono.fromSupplier(() -> calculate(request.arguments()))
* .map(result -> CallToolResult.builder()
* .content(List.of(new McpSchema.TextContent("Result: " + result)))
* .isError(false)
Expand Down Expand Up @@ -441,46 +441,6 @@ public AsyncSpecification<S> capabilities(McpSchema.ServerCapabilities serverCap
return this;
}

/**
* Adds a single tool with its implementation handler to the server. This is a
* convenience method for registering individual tools without creating a
* {@link McpServerFeatures.AsyncToolSpecification} explicitly.
*
* <p>
* Example usage: <pre>{@code
* .tool(
* Tool.builder().name("calculator").title("Performs calculations").inputSchema(schema).build(),
* (exchange, args) -> Mono.fromSupplier(() -> calculate(args))
* .map(result -> CallToolResult.builder()
* .content(List.of(new McpSchema.TextContent("Result: " + result)))
* .isError(false)
* .build()))
* )
* }</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.
* The function's first argument is an {@link McpAsyncServerExchange} upon which
* the server can interact with the connected client. The second argument is the
* map of arguments passed to the tool.
* @return This builder instance for method chaining
* @throws IllegalArgumentException if tool or handler is null
* @deprecated Use {@link #toolCall(McpSchema.Tool, BiFunction)} instead for tool
* calls that require a request object.
*/
@Deprecated
public AsyncSpecification<S> tool(McpSchema.Tool tool,
BiFunction<McpAsyncServerExchange, Map<String, Object>, Mono<CallToolResult>> handler) {
Assert.notNull(tool, "Tool must not be null");
Assert.notNull(handler, "Handler must not be null");
validateToolName(tool.name());
assertNoDuplicateTool(tool.name());

this.tools.add(new McpServerFeatures.AsyncToolSpecification(tool, handler));

return this;
}

/**
* Adds a single tool with its implementation handler to the server. This is a
* convenience method for registering individual tools without creating a
Expand Down Expand Up @@ -1064,45 +1024,6 @@ public SyncSpecification<S> capabilities(McpSchema.ServerCapabilities serverCapa
return this;
}

/**
* Adds a single tool with its implementation handler to the server. This is a
* convenience method for registering individual tools without creating a
* {@link McpServerFeatures.SyncToolSpecification} explicitly.
*
* <p>
* Example usage: <pre>{@code
* .tool(
* Tool.builder().name("calculator").title("Performs calculations".inputSchema(schema).build(),
* (exchange, args) -> CallToolResult.builder()
* .content(List.of(new McpSchema.TextContent("Result: " + calculate(args))))
* .isError(false)
* .build())
* )
* }</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.
* The function's first argument is an {@link McpSyncServerExchange} upon which
* the server can interact with the connected client. The second argument is the
* list of arguments passed to the tool.
* @return This builder instance for method chaining
* @throws IllegalArgumentException if tool or handler is null
* @deprecated Use {@link #toolCall(McpSchema.Tool, BiFunction)} instead for tool
* calls that require a request object.
*/
@Deprecated
public SyncSpecification<S> tool(McpSchema.Tool tool,
BiFunction<McpSyncServerExchange, Map<String, Object>, McpSchema.CallToolResult> handler) {
Assert.notNull(tool, "Tool must not be null");
Assert.notNull(handler, "Handler must not be null");
validateToolName(tool.name());
assertNoDuplicateTool(tool.name());

this.tools.add(new McpServerFeatures.SyncToolSpecification(tool, handler));

return this;
}

/**
* Adds a single tool with its implementation handler to the server. This is a
* convenience method for registering individual tools without creating a
Expand All @@ -1123,7 +1044,7 @@ public SyncSpecification<S> toolCall(McpSchema.Tool tool,
validateToolName(tool.name());
assertNoDuplicateTool(tool.name());

this.tools.add(new McpServerFeatures.SyncToolSpecification(tool, null, handler));
this.tools.add(new McpServerFeatures.SyncToolSpecification(tool, handler));

return this;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -223,19 +223,8 @@ record Sync(McpSchema.Implementation serverInfo, McpSchema.ServerCapabilities se
* map of tool arguments.
*/
public record AsyncToolSpecification(McpSchema.Tool tool,
@Deprecated BiFunction<McpAsyncServerExchange, Map<String, Object>, Mono<McpSchema.CallToolResult>> call,
BiFunction<McpAsyncServerExchange, McpSchema.CallToolRequest, Mono<McpSchema.CallToolResult>> callHandler) {

/**
* @deprecated Use {@link AsyncToolSpecification(McpSchema.Tool, null,
* BiFunction)} instead.
**/
@Deprecated
public AsyncToolSpecification(McpSchema.Tool tool,
BiFunction<McpAsyncServerExchange, Map<String, Object>, Mono<McpSchema.CallToolResult>> call) {
this(tool, call, (exchange, toolReq) -> call.apply(exchange, toolReq.arguments()));
}

static AsyncToolSpecification fromSync(SyncToolSpecification syncToolSpec) {
return fromSync(syncToolSpec, false);
}
Expand All @@ -247,21 +236,14 @@ static AsyncToolSpecification fromSync(SyncToolSpecification syncToolSpec, boole
return null;
}

BiFunction<McpAsyncServerExchange, Map<String, Object>, Mono<McpSchema.CallToolResult>> deprecatedCall = (syncToolSpec
.call() != null) ? (exchange, map) -> {
var toolResult = Mono
.fromCallable(() -> syncToolSpec.call().apply(new McpSyncServerExchange(exchange), map));
return immediate ? toolResult : toolResult.subscribeOn(Schedulers.boundedElastic());
} : null;

BiFunction<McpAsyncServerExchange, McpSchema.CallToolRequest, Mono<McpSchema.CallToolResult>> callHandler = (
exchange, req) -> {
var toolResult = Mono
.fromCallable(() -> syncToolSpec.callHandler().apply(new McpSyncServerExchange(exchange), req));
return immediate ? toolResult : toolResult.subscribeOn(Schedulers.boundedElastic());
};

return new AsyncToolSpecification(syncToolSpec.tool(), deprecatedCall, callHandler);
return new AsyncToolSpecification(syncToolSpec.tool(), callHandler);
}

/**
Expand Down Expand Up @@ -304,7 +286,7 @@ public AsyncToolSpecification build() {
Assert.notNull(tool, "Tool must not be null");
Assert.notNull(callHandler, "Call handler function must not be null");

return new AsyncToolSpecification(tool, null, callHandler);
return new AsyncToolSpecification(tool, callHandler);
}

}
Expand Down Expand Up @@ -523,26 +505,16 @@ static AsyncCompletionSpecification fromSync(SyncCompletionSpecification complet
* }</pre>
*
* @param tool The tool definition including name, description, and parameter schema
* @param call (Deprected) 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
* @param callHandler The function that implements the tool's logic, receiving a
* {@link McpSyncServerExchange} and a
* {@link io.modelcontextprotocol.spec.McpSchema.CallToolRequest} and returning
* results. The function's first argument is an {@link McpSyncServerExchange} upon
* which the server can interact with the client. The second arguments is a map of
* arguments passed to the tool.
* which the server can interact with the client. The second argument is a request
* object containing the arguments passed to the tool.
*/
public record SyncToolSpecification(McpSchema.Tool tool,
@Deprecated BiFunction<McpSyncServerExchange, Map<String, Object>, McpSchema.CallToolResult> call,
BiFunction<McpSyncServerExchange, CallToolRequest, McpSchema.CallToolResult> callHandler) {

@Deprecated
public SyncToolSpecification(McpSchema.Tool tool,
BiFunction<McpSyncServerExchange, Map<String, Object>, McpSchema.CallToolResult> call) {
this(tool, call, (exchange, toolReq) -> call.apply(exchange, toolReq.arguments()));
}

/**
* Builder for creating SyncToolSpecification instances.
*/
Expand Down Expand Up @@ -583,7 +555,7 @@ public SyncToolSpecification build() {
Assert.notNull(tool, "Tool must not be null");
Assert.notNull(callHandler, "CallTool function must not be null");

return new SyncToolSpecification(tool, null, callHandler);
return new SyncToolSpecification(tool, callHandler);
}

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -230,21 +230,6 @@ public void notifyPromptsListChanged() {
this.asyncServer.notifyPromptsListChanged().block();
}

/**
* 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
* @deprecated Use
* {@link McpSyncServerExchange#loggingNotification(LoggingMessageNotification)}
* instead.
*/
@Deprecated
public void loggingNotification(LoggingMessageNotification loggingMessageNotification) {
this.asyncServer.loggingNotification(loggingMessageNotification).block();
}

/**
* Close the server gracefully.
*/
Expand Down
Loading