Skip to content

Commit 187597b

Browse files
authored
feat(elicitation): add support URL elicitation. SEP-1036 (#605)
1 parent edd5b1d commit 187597b

File tree

12 files changed

+1533
-271
lines changed

12 files changed

+1533
-271
lines changed

crates/rmcp/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ default = ["base64", "macros", "server"]
7979
client = ["dep:tokio-stream"]
8080
server = ["transport-async-rw", "dep:schemars", "dep:pastey"]
8181
macros = ["dep:rmcp-macros", "dep:pastey"]
82-
elicitation = []
82+
elicitation = ["dep:url"]
8383

8484
# reqwest http client
8585
__reqwest = ["dep:reqwest"]

crates/rmcp/src/handler/client.rs

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,10 @@ impl<H: ClientHandler> Service<RoleClient> for H {
6262
ServerNotification::PromptListChangedNotification(_notification_no_param) => {
6363
self.on_prompt_list_changed(context).await
6464
}
65+
ServerNotification::ElicitationCompletionNotification(notification) => {
66+
self.on_url_elicitation_notification_complete(notification.params, context)
67+
.await
68+
}
6569
ServerNotification::CustomNotification(notification) => {
6670
self.on_custom_notification(notification, context).await
6771
}
@@ -116,6 +120,44 @@ pub trait ClientHandler: Sized + Send + Sync + 'static {
116120
/// # Default Behavior
117121
/// The default implementation automatically declines all elicitation requests.
118122
/// Real clients should override this to provide user interaction.
123+
///
124+
/// # Example
125+
/// ```rust,ignore
126+
/// use rmcp::model::CreateElicitationRequestParam;
127+
/// use rmcp::{
128+
/// model::ErrorData as McpError,
129+
/// model::*,
130+
/// service::{NotificationContext, RequestContext, RoleClient, Service, ServiceRole},
131+
/// };
132+
/// use rmcp::ClientHandler;
133+
///
134+
/// impl ClientHandler for MyClient {
135+
/// async fn create_elicitation(
136+
/// &self,
137+
/// request: CreateElicitationRequestParam,
138+
/// context: RequestContext<RoleClient>,
139+
/// ) -> Result<CreateElicitationResult, McpError> {
140+
/// match request {
141+
/// CreateElicitationRequestParam::FormElicitationParam {meta, message, requested_schema,} => {
142+
/// // Display message to user and collect input according to requested_schema
143+
/// let user_input = get_user_input(message, requested_schema).await?;
144+
/// Ok(CreateElicitationResult {
145+
/// action: ElicitationAction::Accept,
146+
/// content: Some(user_input),
147+
/// })
148+
/// }
149+
/// CreateElicitationRequestParam::UrlElicitationParam {meta, message, url, elicitation_id,} => {
150+
/// // Open URL in browser for user to complete elicitation
151+
/// open_url_in_browser(url).await?;
152+
/// Ok(CreateElicitationResult {
153+
/// action: ElicitationAction::Accept,
154+
/// content: None,
155+
/// })
156+
/// }
157+
/// }
158+
/// }
159+
/// }
160+
/// ```
119161
fn create_elicitation(
120162
&self,
121163
request: CreateElicitationRequestParams,
@@ -189,6 +231,14 @@ pub trait ClientHandler: Sized + Send + Sync + 'static {
189231
) -> impl Future<Output = ()> + Send + '_ {
190232
std::future::ready(())
191233
}
234+
235+
fn on_url_elicitation_notification_complete(
236+
&self,
237+
params: ElicitationResponseNotificationParam,
238+
context: NotificationContext<RoleClient>,
239+
) -> impl Future<Output = ()> + Send + '_ {
240+
std::future::ready(())
241+
}
192242
fn on_custom_notification(
193243
&self,
194244
notification: CustomNotification,

0 commit comments

Comments
 (0)