Add URL elicitation support (SEP-1036) (#993)

Add URL-type elicitation schema support allowing servers to request URL
input from users during tool execution. This enables out-of-band
interactions like payment processing or API key entry.

Breaking changes:

- `ElicitRequest` changed from a `record` to an `interface`.
- The original `ElicitRequest` record was renamed to `ElicitFormRequest`.
- `McpClient` builder `elicitation()` methods now accept `ElicitFormRequest` instead of `ElicitRequest`.

New APIs:

- `ElicitUrlRequest` record for URL-mode elicitation.
- `urlElicitation()` builder methods in `McpClient`.
- `elicitationCompleteConsumer()` and `elicitationCompleteConsumers()` builder methods in `McpClient`.
- `sendElicitationComplete()` methods in `McpAsyncServer` and `McpSyncServer`.
- `McpError.URL_ELICITATION_REQUIRED` and `McpSchema.ErrorCodes.URL_ELICITATION_REQUIRED`.
- `ElicitationCompleteNotification` record and `METHOD_NOTIFICATION_ELICITATION_COMPLETE` constant.

Co-authored-by: Daniel Garnier-Moiroux <git@garnier.wf>
Co-authored-by: Sainath Reddy Bobbala <bsnr@amazon.com>
This commit is contained in:
Daniel Garnier-Moiroux 2026-06-03 16:24:29 +02:00 • committed by GitHub
commit dbb9bdad51
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -715,9 +715,7 @@ var tool = SyncToolSpecification.builder()
}
// Request user confirmation
ElicitRequest elicitRequest = ElicitRequest.builder()
.message("Do you want to proceed with this action?")
.requestedSchema(Map.of(
ElicitRequest elicitRequest = ElicitFormRequest.builder("Do you want to proceed with this action?", Map.of(
"type", "object",
"properties", Map.of("confirmed", Map.of("type", "boolean"))
))
@ -739,6 +737,40 @@ var tool = SyncToolSpecification.builder()
.build();
```
To request out-of-band URL elicitation, such as a user authorizing an OAuth flow:
```java
var urlTool = SyncToolSpecification.builder()
.tool(Tool.builder()
.name("oauth-auth")
.description("Authenticates via OAuth")
.inputSchema(schema)
.build())
.callHandler((exchange, request) -> {
// Request URL elicitation from client
if (
exchange.getClientCapabilities().elicitation() != null
&& exchange.getClientCapabilities().elicitation().url() != null
) {
ElicitRequest urlRequest = McpSchema.ElicitUrlRequest
.builder("Please authenticate", "https://example.com/oauth", "oauth-123").build();
ElicitResult result = exchange.elicit(urlRequest);
// handle result.action == CANCELLED or DENIED
if (result.action() != ElicitResult.Action.ACCEPT) {
return CallToolResult.builder()
.content(List.of(new McpSchema.TextContent("Authentication failed or cancelled")))
.build();
}
}
// wait for user to visit the URL
return CallToolResult.builder()
.content(List.of(new McpSchema.TextContent("Authentication successful")))
.build();
})
.build();
```
### Logging Support
The server provides structured logging capabilities that allow sending log messages to clients with different severity levels.