1
1
// cargo test --features "server client" --package rmcp test_elicitation
2
+ #![ cfg( feature = "mcp_spec-2025-06-18" ) ]
2
3
mod common;
3
4
4
5
use std:: sync:: { Arc , Mutex } ;
5
6
6
7
use common:: handlers:: { TestClientHandler , TestServer } ;
7
- use rmcp:: {
8
- ServiceExt ,
9
- model:: { CreateElicitationRequestParam , CreateElicitationResult , ElicitationAction } ,
10
- } ;
8
+ use rmcp:: { ServiceExt , model:: * } ;
11
9
use serde_json:: json;
12
10
use tokio:: sync:: Notify ;
13
11
@@ -30,7 +28,12 @@ async fn test_elicitation_spec_compliance() -> anyhow::Result<()> {
30
28
received_requests : Arc < Mutex < Vec < CreateElicitationRequestParam > > > ,
31
29
) -> Self {
32
30
Self {
33
- inner : TestClientHandler :: with_notification ( false , false , receive_signal. clone ( ) , Arc :: new ( Mutex :: new ( Vec :: new ( ) ) ) ) ,
31
+ inner : TestClientHandler :: with_notification (
32
+ false ,
33
+ false ,
34
+ receive_signal. clone ( ) ,
35
+ Arc :: new ( Mutex :: new ( Vec :: new ( ) ) ) ,
36
+ ) ,
34
37
receive_signal,
35
38
received_requests,
36
39
}
@@ -48,10 +51,10 @@ async fn test_elicitation_spec_compliance() -> anyhow::Result<()> {
48
51
let mut requests = self . received_requests . lock ( ) . unwrap ( ) ;
49
52
requests. push ( params. clone ( ) ) ;
50
53
}
51
-
54
+
52
55
// Signal that we received a request
53
56
self . receive_signal . notify_one ( ) ;
54
-
57
+
55
58
// Simulate user accepting the elicitation with test data
56
59
Ok ( CreateElicitationResult {
57
60
action : ElicitationAction :: Accept ,
@@ -121,7 +124,7 @@ async fn test_elicitation_spec_compliance() -> anyhow::Result<()> {
121
124
// Verify the response
122
125
assert_eq ! ( result. action, ElicitationAction :: Accept ) ;
123
126
assert ! ( result. content. is_some( ) ) ;
124
-
127
+
125
128
let content = result. content . unwrap ( ) ;
126
129
assert_eq ! ( content
[ "email" ] , "[email protected] " ) ;
127
130
assert_eq ! ( content[ "age" ] , 25 ) ;
@@ -131,24 +134,26 @@ async fn test_elicitation_spec_compliance() -> anyhow::Result<()> {
131
134
anyhow:: Ok ( ( ) )
132
135
} ) ;
133
136
134
- let client = ElicitationTestClientHandler :: new (
135
- receive_signal. clone ( ) ,
136
- received_requests. clone ( ) ,
137
- )
138
- . serve ( client_transport)
139
- . await ?;
137
+ let client =
138
+ ElicitationTestClientHandler :: new ( receive_signal. clone ( ) , received_requests. clone ( ) )
139
+ . serve ( client_transport)
140
+ . await ?;
140
141
141
142
// Wait for the elicitation request
142
143
receive_signal. notified ( ) . await ;
143
-
144
+
144
145
// Verify the request was received correctly
145
146
{
146
147
let requests = received_requests. lock ( ) . unwrap ( ) ;
147
- assert_eq ! ( requests. len( ) , 1 , "Should receive exactly one elicitation request" ) ;
148
-
148
+ assert_eq ! (
149
+ requests. len( ) ,
150
+ 1 ,
151
+ "Should receive exactly one elicitation request"
152
+ ) ;
153
+
149
154
let request = & requests[ 0 ] ;
150
155
assert_eq ! ( request. message, "Please provide your contact information" ) ;
151
-
156
+
152
157
// Verify the schema structure
153
158
let schema = & request. requested_schema ;
154
159
assert ! ( schema[ "type" ] . as_str( ) . unwrap( ) == "object" ) ;
@@ -165,11 +170,8 @@ async fn test_elicitation_spec_compliance() -> anyhow::Result<()> {
165
170
Ok ( ( ) )
166
171
}
167
172
168
- #[ tokio:: test]
173
+ #[ tokio:: test]
169
174
async fn test_elicitation_action_types ( ) -> anyhow:: Result < ( ) > {
170
- let ( server_transport, client_transport) = tokio:: io:: duplex ( 4096 ) ;
171
- let receive_signal = Arc :: new ( Notify :: new ( ) ) ;
172
-
173
175
// Test different action types
174
176
for ( action_type, expected_action) in [
175
177
( "accept" , ElicitationAction :: Accept ) ,
@@ -178,7 +180,7 @@ async fn test_elicitation_action_types() -> anyhow::Result<()> {
178
180
] {
179
181
let ( server_transport, client_transport) = tokio:: io:: duplex ( 4096 ) ;
180
182
let receive_signal = Arc :: new ( Notify :: new ( ) ) ;
181
-
183
+
182
184
struct ActionTestClientHandler {
183
185
action : ElicitationAction ,
184
186
receive_signal : Arc < Notify > ,
@@ -191,7 +193,7 @@ async fn test_elicitation_action_types() -> anyhow::Result<()> {
191
193
_context : rmcp:: service:: RequestContext < rmcp:: service:: RoleClient > ,
192
194
) -> Result < CreateElicitationResult , rmcp:: Error > {
193
195
self . receive_signal . notify_one ( ) ;
194
-
196
+
195
197
Ok ( CreateElicitationResult {
196
198
action : self . action . clone ( ) ,
197
199
content : match self . action {
@@ -226,12 +228,12 @@ async fn test_elicitation_action_types() -> anyhow::Result<()> {
226
228
. await ?;
227
229
228
230
assert_eq ! ( result. action, expected_action) ;
229
-
231
+
230
232
match expected_action {
231
233
ElicitationAction :: Accept => {
232
234
assert ! ( result. content. is_some( ) ) ;
233
235
assert_eq ! ( result. content. unwrap( ) [ "test" ] , "data" ) ;
234
- } ,
236
+ }
235
237
_ => {
236
238
assert ! ( result. content. is_none( ) ) ;
237
239
}
@@ -262,11 +264,20 @@ fn test_elicitation_serialization() {
262
264
for ( action, expected) in test_cases {
263
265
let serialized = serde_json:: to_string ( & action) . unwrap ( ) ;
264
266
let serialized = serialized. trim_matches ( '"' ) ;
265
- assert_eq ! ( serialized, expected, "ElicitationAction::{:?} should serialize to \" {}\" " , action, expected) ;
266
-
267
+ assert_eq ! (
268
+ serialized, expected,
269
+ "ElicitationAction::{:?} should serialize to \" {}\" " ,
270
+ action, expected
271
+ ) ;
272
+
267
273
// Test deserialization
268
- let deserialized: ElicitationAction = serde_json:: from_str ( & format ! ( "\" {}\" " , expected) ) . unwrap ( ) ;
269
- assert_eq ! ( deserialized, action, "\" {}\" should deserialize to ElicitationAction::{:?}" , expected, action) ;
274
+ let deserialized: ElicitationAction =
275
+ serde_json:: from_str ( & format ! ( "\" {}\" " , expected) ) . unwrap ( ) ;
276
+ assert_eq ! (
277
+ deserialized, action,
278
+ "\" {}\" should deserialize to ElicitationAction::{:?}" ,
279
+ expected, action
280
+ ) ;
270
281
}
271
282
272
283
// Test CreateElicitationRequestParam serialization
@@ -302,5 +313,8 @@ fn test_elicitation_serialization() {
302
313
303
314
let serialized = serde_json:: to_value ( & result_no_content) . unwrap ( ) ;
304
315
assert_eq ! ( serialized[ "action" ] , "cancel" ) ;
305
- assert ! ( serialized. get( "content" ) . is_none( ) , "content field should be omitted when None" ) ;
306
- }
316
+ assert ! (
317
+ serialized. get( "content" ) . is_none( ) ,
318
+ "content field should be omitted when None"
319
+ ) ;
320
+ }
0 commit comments