Skip to content

Commit 174af7e

Browse files
committed
feat: add elicitation capability checking for server methods
- Add supports_elicitation() method to check client capabilities - Add CapabilityNotSupported error variant to ElicitationError - Update elicit_structured_input() to check capabilities before execution - Update elicit<T>() method to check capabilities before execution - Add comprehensive tests for capability checking functionality - Tests verify that servers check client capabilities before sending elicitation requests - Ensures compliance with MCP 2025-06-18 specification requirement
1 parent e1a995c commit 174af7e

File tree

2 files changed

+320
-65
lines changed

2 files changed

+320
-65
lines changed

crates/rmcp/src/service/server.rs

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -348,6 +348,10 @@ pub enum ElicitationError {
348348
/// No response content was provided by the user
349349
#[error("No response content provided")]
350350
NoContent,
351+
352+
/// Client does not support elicitation capability
353+
#[error("Client does not support elicitation - capability not declared during initialization")]
354+
CapabilityNotSupported,
351355
}
352356

353357
impl Peer<RoleServer> {
@@ -367,6 +371,19 @@ impl Peer<RoleServer> {
367371
// ELICITATION CONVENIENCE METHODS
368372
// =============================================================================
369373

374+
/// Check if the client supports elicitation capability
375+
///
376+
/// Returns true if the client declared elicitation capability during initialization,
377+
/// false otherwise. According to MCP 2025-06-18 specification, clients that support
378+
/// elicitation MUST declare the capability during initialization.
379+
pub fn supports_elicitation(&self) -> bool {
380+
if let Some(client_info) = self.peer_info() {
381+
client_info.capabilities.elicitation.is_some()
382+
} else {
383+
false
384+
}
385+
}
386+
370387
/// Request structured data from the user using a custom JSON schema.
371388
///
372389
/// This is the most flexible elicitation method, allowing you to request
@@ -410,7 +427,12 @@ impl Peer<RoleServer> {
410427
&self,
411428
message: impl Into<String>,
412429
schema: &crate::model::JsonObject,
413-
) -> Result<Option<serde_json::Value>, ServiceError> {
430+
) -> Result<Option<serde_json::Value>, ElicitationError> {
431+
// Check if client supports elicitation capability
432+
if !self.supports_elicitation() {
433+
return Err(ElicitationError::CapabilityNotSupported);
434+
}
435+
414436
let response = self
415437
.create_elicitation(CreateElicitationRequestParam {
416438
message: message.into(),
@@ -493,6 +515,11 @@ impl Peer<RoleServer> {
493515
where
494516
T: schemars::JsonSchema + for<'de> serde::Deserialize<'de>,
495517
{
518+
// Check if client supports elicitation capability
519+
if !self.supports_elicitation() {
520+
return Err(ElicitationError::CapabilityNotSupported);
521+
}
522+
496523
// Generate schema automatically from type
497524
let schema = crate::handler::server::tool::schema_for_type::<T>();
498525

0 commit comments

Comments
 (0)