Skip to content

chore: fix all clippy warnings - #746

Merged
alexhancock merged 1 commit into
mainfrom
chore/fix-clippy-warnings
Mar 11, 2026
Merged

chore: fix all clippy warnings#746
alexhancock merged 1 commit into
mainfrom
chore/fix-clippy-warnings

Conversation

@DaleSeo

@DaleSeoDaleSeo commented Mar 11, 2026

Copy link
Copy Markdown
Member

Motivation and Context

This PR resolves all the clippy issues, allowing the CI clippy gate to pass cleanly.

❯ cargo clippy --workspace --all-targets --all-features
warning: /Users/dale.seo/work/rust-sdk/crates/rmcp/Cargo.toml: only one of `license` or `license-file` is necessary
`license` should be used if the package license can be expressed with a standard SPDX expression.
`license-file` should be used if the package uses a non-standard license.
See https://doc.rust-lang.org/cargo/reference/manifest.html#the-license-and-license-file-fields for more information.
warning: /Users/dale.seo/work/rust-sdk/crates/rmcp-macros/Cargo.toml: only one of `license` or `license-file` is necessary
`license` should be used if the package license can be expressed with a standard SPDX expression.
`license-file` should be used if the package uses a non-standard license.
See https://doc.rust-lang.org/cargo/reference/manifest.html#the-license-and-license-file-fields for more information.
Compiling rmcp v1.2.0 (/Users/dale.seo/work/rust-sdk/crates/rmcp)
Compiling rmcp-macros v1.2.0 (/Users/dale.seo/work/rust-sdk/crates/rmcp-macros)
Checking simple-chat-client v0.1.0 (/Users/dale.seo/work/rust-sdk/examples/simple-chat-client)
Checking mcp-server-examples v0.1.5 (/Users/dale.seo/work/rust-sdk/examples/servers)
Checking mcp-client-examples v0.1.5 (/Users/dale.seo/work/rust-sdk/examples/clients)
Checking transport v1.2.0 (/Users/dale.seo/work/rust-sdk/examples/transport)
warning: unused import: `chrono::Utc`
--> examples/servers/src/common/counter.rs:4:5
|
4 | use chrono::Utc;| ^^^^^^^^^^^
|
= note: `#[warn(unused_imports)]` on by default
warning: unused imports: `OperationDescriptor` and `OperationMessage`
--> examples/servers/src/common/counter.rs:16:9
|
16 | OperationDescriptor, OperationMessage, OperationProcessor, OperationResultTransport,
| ^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^
warning: unused import: `tracing::info`
--> examples/servers/src/common/counter.rs:22:5
|
22 | use tracing::info;| ^^^^^^^^^^^^^
Checking rig-integration v1.2.0 (/Users/dale.seo/work/rust-sdk/examples/rig-integration)
Checking wasi-mcp-example v1.2.0 (/Users/dale.seo/work/rust-sdk/examples/wasi)
warning: `mcp-server-examples` (example "counter_hyper_streamable_http") generated 3 warnings (run `cargo clippy --fix --example "counter_hyper_streamable_http"` to apply 3 suggestions)
warning: `mcp-server-examples` (example "servers_memory_stdio") generated 3 warnings (3 duplicates)
warning: unused import: `Serialize`
--> examples/servers/src/cimd_auth_streamhttp.rs:21:26
|
21 | use serde::{Deserialize, Serialize};| ^^^^^^^^^
|
= note: `#[warn(unused_imports)]` on by default
warning: unused import: `chrono::Utc`
--> examples/servers/src/common/counter.rs:4:5
|
4 | use chrono::Utc;| ^^^^^^^^^^^
warning: `mcp-server-examples` (example "servers_progress_demo") generated 3 warnings (3 duplicates)
warning: fields `client_id` and `redirect_uri` are never read
--> examples/servers/src/cimd_auth_streamhttp.rs:38:5
|
37 | struct AuthCodeRecord {
| -------------- fields in this struct
38 | client_id: String,
| ^^^^^^^^^
39 | redirect_uri: String,
| ^^^^^^^^^^^^
|
= note: `AuthCodeRecord` has derived impls for the traits `Debug` and `Clone`, but these are intentionally ignored during dead code analysis
= note: `#[warn(dead_code)]` on by default
warning: `mcp-server-examples` (example "servers_cimd_auth_streamhttp") generated 5 warnings (2 duplicates) (run `cargo clippy --fix --example "servers_cimd_auth_streamhttp"` to apply 2 suggestions)
Checking mcp-conformance v0.1.0 (/Users/dale.seo/work/rust-sdk/conformance)
warning: `mcp-server-examples` (example "servers_calculator_stdio") generated 3 warnings (3 duplicates)
warning: `mcp-server-examples` (example "servers_counter_stdio") generated 3 warnings (3 duplicates)
warning: `mcp-server-examples` (example "servers_counter_streamhttp") generated 3 warnings (3 duplicates)
warning: `mcp-server-examples` (example "servers_simple_auth_streamhttp") generated 3 warnings (3 duplicates)
warning: this functioncan be simplified using the `async fn` syntax
--> conformance/src/bin/client.rs:58:5
|
58 | / fn create_elicitation(
59 ||&self,
60 || request: CreateElicitationRequestParams,
61 || _cx: RequestContext<RoleClient>,
62 || ) -> impl Future<Output = Result<CreateElicitationResult, ErrorData>> + Send + '_ { | |_____________________________________________________________________________________^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#manual_async_fn = note: `#[warn(clippy::manual_async_fn)]` on by defaulthelp: make the function `async` and return the output of the future directly |58 ~ async fn create_elicitation(59 + &self,60 + request: CreateElicitationRequestParams,61 + _cx: RequestContext<RoleClient>,62 ~ ) -> Result<CreateElicitationResult, ErrorData> {63 + let content = match &request {64 + CreateElicitationRequestParams::FormElicitationParams {65 + requested_schema, ..66 + } => {67 + let mut defaults = serde_json::Map::new();68 + for (name, prop) in &requested_schema.properties {69 + match prop {70 + PrimitiveSchema::String(s) => {71 + if let Some(d) = &s.default {72 + defaults.insert(name.clone(), Value::String(d.clone()));73 + }74 + }75 + PrimitiveSchema::Number(n) => {76 + if let Some(d) = n.default {77 + defaults.insert(name.clone(), json!(d));78 + }79 + }80 + PrimitiveSchema::Integer(i) => {81 + if let Some(d) = i.default {82 + defaults.insert(name.clone(), json!(d));83 + }84 + }85 + PrimitiveSchema::Boolean(b) => {86 + if let Some(d) = b.default {87 + defaults.insert(name.clone(), Value::Bool(d));88 + }89 + }90 + PrimitiveSchema::Enum(e) => {91 + let val = match e {92 + EnumSchema::Single(SingleSelectEnumSchema::Untitled(u)) => {93 + u.default.as_ref().map(|d| Value::String(d.clone()))94 + }95 + EnumSchema::Single(SingleSelectEnumSchema::Titled(t)) => {96 + t.default.as_ref().map(|d| Value::String(d.clone()))97 + }98 + EnumSchema::Multi(MultiSelectEnumSchema::Untitled(u)) => {99 + u.default.as_ref().map(|d| {100+ Value::Array(101+ d.iter()102+ .map(|s| Value::String(s.clone()))103+ .collect(),104+ )105+ })106+ }107+ EnumSchema::Multi(MultiSelectEnumSchema::Titled(t)) => {108+ t.default.as_ref().map(|d| {109+ Value::Array(110+ d.iter()111+ .map(|s| Value::String(s.clone()))112+ .collect(),113+ )114+ })115+ }116+ EnumSchema::Legacy(_) => None,117+ };118+ if let Some(v) = val {119+ defaults.insert(name.clone(), v);120+ }121+ }122+ }123+ }124+ Some(Value::Object(defaults))125+ }126+ _ => Some(json!({})),127+ };128+ Ok(CreateElicitationResult {129+ action: ElicitationAction::Accept,130+ content,131+ })132+ } |warning: this function can be simplified using the `async fn` syntax --> conformance/src/bin/client.rs:152:5 |152 | / fn create_message(153 | | &self,154 | | params: CreateMessageRequestParams,155 | | _cx: RequestContext<RoleClient>,156 | | ) -> impl Future<Output = Result<CreateMessageResult, ErrorData>> + Send + '_ {
||_________________________________________________________________________________^
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#manual_async_fn
help: make the function`async` and return the output of the future directly
|
152 ~ async fn create_message(
153 + &self,
154 + params: CreateMessageRequestParams,
155 + _cx: RequestContext<RoleClient>,
156 ~ ) -> Result<CreateMessageResult, ErrorData> {
157 + let prompt_text = params
158 + .messages
159 + .first()
160 + .and_then(|m|m.content.first())
161 + .and_then(|c|c.as_text())
162 + .map(|t|t.text.clone())
163 + .unwrap_or_default();
164 + Ok(CreateMessageResult::new(
165 + SamplingMessage::new(
166 + Role::Assistant,
167 + SamplingMessageContent::text(format!(
168 + "This is a mock LLM response to: {}",
169 + prompt_text
170 + )),
171 + ),
172 + "mock-model".into(),
173 + )
174 + .with_stop_reason("endTurn"))
175 + }
|
warning: this functioncan be simplified using the `async fn` syntax
--> conformance/src/bin/client.rs:179:5
|
179 | / fn create_elicitation(
180 ||&self,
181 || _request: CreateElicitationRequestParams,
182 || _cx: RequestContext<RoleClient>,
183 || ) -> impl Future<Output = Result<CreateElicitationResult, ErrorData>> + Send + '_ { | |_____________________________________________________________________________________^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#manual_async_fnhelp: make the function `async` and return the output of the future directly |179 ~ async fn create_elicitation(180 + &self,181 + _request: CreateElicitationRequestParams,182 + _cx: RequestContext<RoleClient>,183 ~ ) -> Result<CreateElicitationResult, ErrorData> {184 + Ok(CreateElicitationResult {185 + action: ElicitationAction::Accept,186 + content: Some(json!({"username": "testuser", "email": "test@example.com"})),187 + })188 + } |warning: this `let...else` may be rewritten with the `?` operator --> conformance/src/bin/client.rs:764:5 |764 | / let Some(properties) = properties else {765 | | return None;766 | | }; | |______^ help: replace it with: `let properties = properties?;` | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#question_mark = note: `#[warn(clippy::question_mark)]` on by defaultwarning: `mcp-conformance` (bin "conformance-client") generated 4 warnings (run `cargo clippy --fix --bin "conformance-client"` to apply 3 suggestions)warning: doc list item without indentation --> examples/servers/src/elicitation_enum_inference.rs:8:5 |8 | //! For more details, see: https://docs.rs/schemars/latest/schemars/ | ^ | = help: if this is supposed to be its own paragraph, add a blank line = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#doc_lazy_continuation = note: `#[warn(clippy::doc_lazy_continuation)]` on by defaulthelp: indent this line |8 | //! For more details, see: https://docs.rs/schemars/latest/schemars/ | ++warning: `mcp-server-examples` (example "elicitation_enum_select") generated 1 warningwarning: `mcp-server-examples` (example "servers_complex_auth_streamhttp") generated 3 warnings (3 duplicates)warning: `mcp-conformance` (bin "conformance-client" test) generated 4 warnings (4 duplicates)warning: this function can be simplified using the `async fn` syntax --> conformance/src/bin/server.rs:45:5 |45 | / fn initialize(46 | | &self,47 | | _request: InitializeRequestParams,48 | | _cx: RequestContext<RoleServer>,49 | | ) -> impl Future<Output = Result<InitializeResult, ErrorData>> + Send + '_ {
||______________________________________________________________________________^
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#manual_async_fn
= note: `#[warn(clippy::manual_async_fn)]` on by default
help: make the function`async` and return the output of the future directly
|
45 ~ async fn initialize(
46 + &self,
47 + _request: InitializeRequestParams,
48 + _cx: RequestContext<RoleServer>,
49 ~ ) -> Result<InitializeResult, ErrorData> {
50 + Ok(InitializeResult::new(
51 + ServerCapabilities::builder()
52 + .enable_prompts()
53 + .enable_resources()
54 + .enable_tools()
55 + .enable_logging()
56 + .build(),
57 + )
58 + .with_server_info(Implementation::new("rust-conformance-server", "0.1.0"))
59 + .with_instructions("Rust MCP conformance test server"))
60 + }
|
warning: this functioncan be simplified using the `async fn` syntax
--> conformance/src/bin/server.rs:64:5
|
64 | / fn ping(
65 ||&self,
66 || _cx: RequestContext<RoleServer>,
67 || ) -> impl Future<Output = Result<(), ErrorData>> + Send + '_ { | |________________________________________________________________^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#manual_async_fnhelp: make the function `async` and return the output of the future directly |64 ~ async fn ping(65 + &self,66 + _cx: RequestContext<RoleServer>,67 ~ ) -> Result<(), ErrorData> { Ok(()) } |warning: this function can be simplified using the `async fn` syntax --> conformance/src/bin/server.rs:71:5 |71 | / fn list_tools(72 | | &self,73 | | _request: Option<PaginatedRequestParams>,74 | | _cx: RequestContext<RoleServer>,75 | | ) -> impl Future<Output = Result<ListToolsResult, ErrorData>> + Send + '_ {
||_____________________________________________________________________________^
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#manual_async_fn
help: make the function`async` and return the output of the future directly
|
71 ~ async fn list_tools(
72 + &self,
73 + _request: Option<PaginatedRequestParams>,
74 + _cx: RequestContext<RoleServer>,
75 ~ ) -> Result<ListToolsResult, ErrorData> {
76 + let tools = vec![
77 + Tool::new(
78 + "test_simple_text",
79 + "Returns simple text content",
80 + json_object(json!({
81 + "type": "object",
82 + "properties": {}
83 + })),
84 + ),
85 + Tool::new(
86 + "test_image_content",
87 + "Returns image content",
88 + json_object(json!({
89 + "type": "object",
90 + "properties": {}
91 + })),
92 + ),
93 + Tool::new(
94 + "test_audio_content",
95 + "Returns audio content",
96 + json_object(json!({
97 + "type": "object",
98 + "properties": {}
99 + })),
100+ ),
101+ Tool::new(
102+ "test_embedded_resource",
103+ "Returns embedded resource content",
104+ json_object(json!({
105+ "type": "object",
106+ "properties": {}
107+ })),
108+ ),
109+ Tool::new(
110+ "test_multiple_content_types",
111+ "Returns multiple content types",
112+ json_object(json!({
113+ "type": "object",
114+ "properties": {}
115+ })),
116+ ),
117+ Tool::new(
118+ "test_tool_with_logging",
119+ "Sends logging notifications during execution",
120+ json_object(json!({
121+ "type": "object",
122+ "properties": {}
123+ })),
124+ ),
125+ Tool::new(
126+ "test_error_handling",
127+ "Always returns an error",
128+ json_object(json!({
129+ "type": "object",
130+ "properties": {}
131+ })),
132+ ),
133+ Tool::new(
134+ "test_tool_with_progress",
135+ "Reports progress notifications",
136+ json_object(json!({
137+ "type": "object",
138+ "properties": {}
139+ })),
140+ ),
141+ Tool::new(
142+ "test_sampling",
143+ "Requests LLM sampling from client",
144+ json_object(json!({
145+ "type": "object",
146+ "properties": {
147+ "prompt": { "type": "string", "description": "The prompt to send" }
148+ },
149+ "required": ["prompt"]
150+ })),
151+ ),
152+ Tool::new(
153+ "test_elicitation",
154+ "Requests user input from client",
155+ json_object(json!({
156+ "type": "object",
157+ "properties": {
158+ "message": { "type": "string", "description": "The message to show" }
159+ },
160+ "required": ["message"]
161+ })),
162+ ),
163+ Tool::new(
164+ "test_elicitation_sep1034_defaults",
165+ "Tests elicitation with default values (SEP-1034)",
166+ json_object(json!({
167+ "type": "object",
168+ "properties": {}
169+ })),
170+ ),
171+ Tool::new(
172+ "test_elicitation_sep1330_enums",
173+ "Tests enum schema improvements (SEP-1330)",
174+ json_object(json!({
175+ "type": "object",
176+ "properties": {}
177+ })),
178+ ),
179+ Tool::new(
180+ "json_schema_2020_12_tool",
181+ "Tool with JSON Schema 2020-12 features",
182+ json_object(json!({
183+ "$schema": "https://json-schema.org/draft/2020-12/schema",
184+ "type": "object",
185+ "$defs": {
186+ "address": {
187+ "type": "object",
188+ "properties": {
189+ "street": { "type": "string" },
190+ "city": { "type": "string" }
191+ }
192+ }
193+ },
194+ "properties": {
195+ "name": { "type": "string" },
196+ "address": { "$ref": "#/$defs/address" }
197+ },
198+ "additionalProperties": false
199+ })),
200+ ),
201+ Tool::new(
202+ "test_reconnection",
203+ "Tests SSE reconnection behavior",
204+ json_object(json!({
205+ "type": "object",
206+ "properties": {}
207+ })),
208+ ),
209+ ];
210+ Ok(ListToolsResult {
211+ meta: None,
212+ tools,
213+ next_cursor: None,
214+ })
215+ }
|
warning: this functioncan be simplified using the `async fn` syntax
--> conformance/src/bin/server.rs:219:5
|
219 | / fn call_tool(
220 ||&self,
221 || request: CallToolRequestParams,
222 || cx: RequestContext<RoleServer>,
223 || ) -> impl Future<Output = Result<CallToolResult, ErrorData>> + Send + '_ { | |____________________________________________________________________________^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#manual_async_fnhelp: make the function `async` and return the output of the future directly |219 ~ async fn call_tool(220 + &self,221 + request: CallToolRequestParams,222 + cx: RequestContext<RoleServer>,223 ~ ) -> Result<CallToolResult, ErrorData> {224 + let args = request.arguments.unwrap_or_default();225 + match request.name.as_ref() {226 + "test_simple_text" => Ok(CallToolResult::success(vec![Content::text(227 + "This is a simple text response for testing.",228 + )])),229 + 230 + "test_image_content" => Ok(CallToolResult::success(vec![Content::image(231 + TEST_IMAGE_DATA,232 + "image/png",233 + )])),234 + 235 + "test_audio_content" => {236 + // No Content::audio() helper, construct manually237 + let audio = RawContent::Audio(RawAudioContent {238 + data: TEST_AUDIO_DATA.into(),239 + mime_type: "audio/wav".into(),240 + })241 + .no_annotation();242 + Ok(CallToolResult::success(vec![audio]))243 + }244 + 245 + "test_embedded_resource" => Ok(CallToolResult::success(vec![Content::resource(246 + ResourceContents::TextResourceContents {247 + uri: "test://embedded-resource".into(),248 + mime_type: Some("text/plain".into()),249 + text: "This is an embedded resource content.".into(),250 + meta: None,251 + },252 + )])),253 + 254 + "test_multiple_content_types" => Ok(CallToolResult::success(vec![255 + Content::text("Multiple content types test:"),256 + Content::image(TEST_IMAGE_DATA, "image/png"),257 + Content::resource(ResourceContents::TextResourceContents {258 + uri: "test://mixed-content-resource".into(),259 + mime_type: Some("application/json".into()),260 + text: r#"{"test":"data","value":123}"#.into(),261 + meta: None,262 + }),263 + ])),264 + 265 + "test_tool_with_logging" => {266 + for msg in [267 + "Tool execution started",268 + "Tool processing data",269 + "Tool execution completed",270 + ] {271 + let _ = cx272 + .peer273 + .notify_logging_message(LoggingMessageNotificationParam {274 + level: LoggingLevel::Info,275 + logger: Some("conformance-server".into()),276 + data: json!(msg),277 + })278 + .await;279 + tokio::time::sleep(tokio::time::Duration::from_millis(50)).await;280 + }281 + 282 + Ok(CallToolResult::success(vec![Content::text(283 + "Logging test completed",284 + )]))285 + }286 + 287 + "test_error_handling" => Ok(CallToolResult::error(vec![Content::text(288 + "This tool intentionally returns an error for testing",289 + )])),290 + 291 + "test_tool_with_progress" => {292 + let progress_token = cx.meta.get_progress_token();293 + 294 + for (progress, message) in295 + [(0.0, "Starting"), (50.0, "Halfway"), (100.0, "Complete")]296 + {297 + if let Some(token) = &progress_token {298 + let _ = cx299 + .peer300 + .notify_progress(ProgressNotificationParam {301 + progress_token: token.clone(),302 + progress,303 + total: Some(100.0),304 + message: Some(message.into()),305 + })306 + .await;307 + }308 + tokio::time::sleep(tokio::time::Duration::from_millis(50)).await;309 + }310 + 311 + Ok(CallToolResult::success(vec![Content::text(312 + "Progress test completed",313 + )]))314 + }315 + 316 + "test_sampling" => {317 + let prompt = args318 + .get("prompt")319 + .and_then(|v| v.as_str())320 + .unwrap_or("Hello");321 + 322 + match cx323 + .peer324 + .create_message(CreateMessageRequestParams::new(325 + vec![SamplingMessage::user_text(prompt)],326 + 100,327 + ))328 + .await329 + {330 + Ok(result) => {331 + let text = result332 + .message333 + .content334 + .first()335 + .and_then(|c| c.as_text())336 + .map(|t| t.text.clone())337 + .unwrap_or_else(|| "No text response".into());338 + Ok(CallToolResult::success(vec![Content::text(format!(339 + "LLM response: {}",340 + text341 + ))]))342 + }343 + Err(e) => Ok(CallToolResult::error(vec![Content::text(format!(344 + "Sampling error: {}",345 + e346 + ))])),347 + }348 + }349 + 350 + "test_elicitation" => {351 + let message = args352 + .get("message")353 + .and_then(|v| v.as_str())354 + .unwrap_or("Please provide your information");355 + 356 + let schema_json = json!({357 + "type": "object",358 + "properties": {359 + "username": {360 + "type": "string",361 + "description": "User's response"362 + },363 + "email": {364 + "type": "string",365 + "description": "User's email address"366 + }367 + },368 + "required": ["username", "email"]369 + });370 + 371 + let schema: ElicitationSchema = serde_json::from_value(schema_json).unwrap();372 + 373 + match cx374 + .peer375 + .create_elicitation(CreateElicitationRequestParams::FormElicitationParams {376 + meta: None,377 + message: message.into(),378 + requested_schema: schema,379 + })380 + .await381 + {382 + Ok(result) => Ok(CallToolResult::success(vec![Content::text(format!(383 + "User response: action={}, content={:?}",384 + match result.action {385 + ElicitationAction::Accept => "accept",386 + ElicitationAction::Decline => "decline",387 + ElicitationAction::Cancel => "cancel",388 + },389 + result.content390 + ))])),391 + Err(e) => Ok(CallToolResult::error(vec![Content::text(format!(392 + "Elicitation error: {}",393 + e394 + ))])),395 + }396 + }397 + 398 + "test_elicitation_sep1034_defaults" => {399 + let schema_json = json!({400 + "type": "object",401 + "properties": {402 + "name": {403 + "type": "string",404 + "description": "User's name",405 + "default": "John Doe"406 + },407 + "age": {408 + "type": "integer",409 + "description": "User's age",410 + "default": 30411 + },412 + "score": {413 + "type": "number",414 + "description": "User's score",415 + "default": 95.5416 + },417 + "status": {418 + "type": "string",419 + "description": "User's status",420 + "enum": ["active", "inactive", "pending"],421 + "default": "active"422 + },423 + "verified": {424 + "type": "boolean",425 + "description": "Whether user is verified",426 + "default": true427 + }428 + }429 + });430 + 431 + let schema: ElicitationSchema = serde_json::from_value(schema_json).unwrap();432 + 433 + match cx434 + .peer435 + .create_elicitation(CreateElicitationRequestParams::FormElicitationParams {436 + meta: None,437 + message: "Please provide values (all have defaults)".into(),438 + requested_schema: schema,439 + })440 + .await441 + {442 + Ok(result) => Ok(CallToolResult::success(vec![Content::text(format!(443 + "Elicitation completed: action={}, content={:?}",444 + match result.action {445 + ElicitationAction::Accept => "accept",446 + ElicitationAction::Decline => "decline",447 + ElicitationAction::Cancel => "cancel",448 + },449 + result.content450 + ))])),451 + Err(e) => Ok(CallToolResult::error(vec![Content::text(format!(452 + "Elicitation error: {}",453 + e454 + ))])),455 + }456 + }457 + 458 + "test_elicitation_sep1330_enums" => {459 + let schema_json = json!({460 + "type": "object",461 + "properties": {462 + "untitledSingle": {463 + "type": "string",464 + "enum": ["option1", "option2", "option3"]465 + },466 + "titledSingle": {467 + "type": "string",468 + "oneOf": [469 + { "const": "value1", "title": "First Option" },470 + { "const": "value2", "title": "Second Option" },471 + { "const": "value3", "title": "Third Option" }472 + ]473 + },474 + "legacyEnum": {475 + "type": "string",476 + "enum": ["opt1", "opt2", "opt3"],477 + "enumNames": ["Option One", "Option Two", "Option Three"]478 + },479 + "untitledMulti": {480 + "type": "array",481 + "items": {482 + "type": "string",483 + "enum": ["option1", "option2", "option3"]484 + }485 + },486 + "titledMulti": {487 + "type": "array",488 + "items": {489 + "anyOf": [490 + { "const": "value1", "title": "First Choice" },491 + { "const": "value2", "title": "Second Choice" },492 + { "const": "value3", "title": "Third Choice" }493 + ]494 + }495 + }496 + }497 + });498 + 499 + let schema: ElicitationSchema = serde_json::from_value(schema_json).unwrap();500 + 501 + match cx502 + .peer503 + .create_elicitation(CreateElicitationRequestParams::FormElicitationParams {504 + meta: None,505 + message: "Test enum schema improvements".into(),506 + requested_schema: schema,507 + })508 + .await509 + {510 + Ok(result) => Ok(CallToolResult::success(vec![Content::text(format!(511 + "Enum elicitation completed: action={}",512 + match result.action {513 + ElicitationAction::Accept => "accept",514 + ElicitationAction::Decline => "decline",515 + ElicitationAction::Cancel => "cancel",516 + }517 + ))])),518 + Err(e) => Ok(CallToolResult::error(vec![Content::text(format!(519 + "Elicitation error: {}",520 + e521 + ))])),522 + }523 + }524 + 525 + "json_schema_2020_12_tool" => {526 + let name = args.get("name").and_then(|v| v.as_str()).unwrap_or("world");527 + Ok(CallToolResult::success(vec![Content::text(format!(528 + "Hello, {}!",529 + name530 + ))]))531 + }532 + 533 + "test_reconnection" => {534 + tokio::time::sleep(tokio::time::Duration::from_millis(100)).await;535 + Ok(CallToolResult::success(vec![Content::text(536 + "Reconnection test completed",537 + )]))538 + }539 + 540 + _ => Err(ErrorData::invalid_params(541 + format!("Unknown tool: {}", request.name),542 + None,543 + )),544 + }545 + } |warning: this function can be simplified using the `async fn` syntax --> conformance/src/bin/server.rs:549:5 |549 | / fn list_resources(550 | | &self,551 | | _request: Option<PaginatedRequestParams>,552 | | _cx: RequestContext<RoleServer>,553 | | ) -> impl Future<Output = Result<ListResourcesResult, ErrorData>> + Send + '_ {
||_________________________________________________________________________________^
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#manual_async_fn
help: make the function`async` and return the output of the future directly
|
549 ~ async fn list_resources(
550 + &self,
551 + _request: Option<PaginatedRequestParams>,
552 + _cx: RequestContext<RoleServer>,
553 ~ ) -> Result<ListResourcesResult, ErrorData> {
554 + Ok(ListResourcesResult {
555 + meta: None,
556 + resources: vec![
557 + RawResource {
558 + uri: "test://static-text".into(),
559 + name: "Static Text Resource".into(),
560 + title: None,
561 + description: Some("A static text resource for testing".into()),
562 + mime_type: Some("text/plain".into()),
563 + size: None,
564 + icons: None,
565 + meta: None,
566 + }
567 + .no_annotation(),
568 + RawResource {
569 + uri: "test://static-binary".into(),
570 + name: "Static Binary Resource".into(),
571 + title: None,
572 + description: Some("A static binary/blob resource for testing".into()),
573 + mime_type: Some("image/png".into()),
574 + size: None,
575 + icons: None,
576 + meta: None,
577 + }
578 + .no_annotation(),
579 + ],
580 + next_cursor: None,
581 + })
582 + }
|
warning: this functioncan be simplified using the `async fn` syntax
--> conformance/src/bin/server.rs:586:5
|
586 | / fn read_resource(
587 ||&self,
588 || request: ReadResourceRequestParams,
589 || _cx: RequestContext<RoleServer>,
590 || ) -> impl Future<Output = Result<ReadResourceResult, ErrorData>> + Send + '_ { | |________________________________________________________________________________^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#manual_async_fnhelp: make the function `async` and return the output of the future directly |586 ~ async fn read_resource(587 + &self,588 + request: ReadResourceRequestParams,589 + _cx: RequestContext<RoleServer>,590 ~ ) -> Result<ReadResourceResult, ErrorData> {591 + let uri = request.uri.as_str();592 + match uri {593 + "test://static-text" => Ok(ReadResourceResult::new(vec![594 + ResourceContents::TextResourceContents {595 + uri: uri.into(),596 + mime_type: Some("text/plain".into()),597 + text: "This is the content of the static text resource.".into(),598 + meta: None,599 + },600 + ])),601 + "test://static-binary" => Ok(ReadResourceResult::new(vec![602 + ResourceContents::BlobResourceContents {603 + uri: uri.into(),604 + mime_type: Some("image/png".into()),605 + blob: TEST_IMAGE_DATA.into(),606 + meta: None,607 + },608 + ])),609 + _ => {610 + // Check if it matches template: test://template/{id}/data611 + if uri.starts_with("test://template/") && uri.ends_with("/data") {612 + let id = uri613 + .strip_prefix("test://template/")614 + .and_then(|s| s.strip_suffix("/data"))615 + .unwrap_or("unknown");616 + Ok(ReadResourceResult::new(vec![617 + ResourceContents::TextResourceContents {618 + uri: uri.into(),619 + mime_type: Some("application/json".into()),620 + text: format!(621 + r#"{{"id":"{}","templateTest":true,"data":"Data for ID: {}"}}"#,622 + id, id623 + ),624 + meta: None,625 + },626 + ]))627 + } else {628 + Err(ErrorData::resource_not_found(629 + format!("Resource not found: {}", uri),630 + None,631 + ))632 + }633 + }634 + }635 + } |warning: this function can be simplified using the `async fn` syntax --> conformance/src/bin/server.rs:639:5 |639 | / fn list_resource_templates(640 | | &self,641 | | _request: Option<PaginatedRequestParams>,642 | | _cx: RequestContext<RoleServer>,643 | | ) -> impl Future<Output = Result<ListResourceTemplatesResult, ErrorData>> + Send + '_ {
||_________________________________________________________________________________________^
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#manual_async_fn
help: make the function`async` and return the output of the future directly
|
639 ~ async fn list_resource_templates(
640 + &self,
641 + _request: Option<PaginatedRequestParams>,
642 + _cx: RequestContext<RoleServer>,
643 ~ ) -> Result<ListResourceTemplatesResult, ErrorData> {
644 + Ok(ListResourceTemplatesResult {
645 + meta: None,
646 + resource_templates: vec![
647 + RawResourceTemplate {
648 + uri_template: "test://template/{id}/data".into(),
649 + name: "Dynamic Resource".into(),
650 + title: None,
651 + description: Some("A dynamic resource with parameter substitution".into()),
652 + mime_type: Some("application/json".into()),
653 + icons: None,
654 + }
655 + .no_annotation(),
656 + ],
657 + next_cursor: None,
658 + })
659 + }
|
warning: this functioncan be simplified using the `async fn` syntax
--> conformance/src/bin/server.rs:663:5
|
663 | / fn subscribe(
664 ||&self,
665 || request: SubscribeRequestParams,
666 || _cx: RequestContext<RoleServer>,
667 || ) -> impl Future<Output = Result<(), ErrorData>> + Send + '_ { | |________________________________________________________________^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#manual_async_fnhelp: make the function `async` and return the output of the future directly |663 ~ async fn subscribe(664 + &self,665 + request: SubscribeRequestParams,666 + _cx: RequestContext<RoleServer>,667 ~ ) -> Result<(), ErrorData> {668 + let mut subs = self.subscriptions.lock().await;669 + subs.insert(request.uri.to_string());670 + Ok(())671 + } |warning: this function can be simplified using the `async fn` syntax --> conformance/src/bin/server.rs:675:5 |675 | / fn unsubscribe(676 | | &self,677 | | request: UnsubscribeRequestParams,678 | | _cx: RequestContext<RoleServer>,679 | | ) -> impl Future<Output = Result<(), ErrorData>> + Send + '_ {
||________________________________________________________________^
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#manual_async_fn
help: make the function`async` and return the output of the future directly
|
675 ~ async fn unsubscribe(
676 + &self,
677 + request: UnsubscribeRequestParams,
678 + _cx: RequestContext<RoleServer>,
679 ~ ) ->Result<(), ErrorData> {
680 + let mut subs = self.subscriptions.lock().await;
681 + subs.remove(request.uri.as_str());
682 + Ok(())
683 + }
|
warning: this functioncan be simplified using the `async fn` syntax
--> conformance/src/bin/server.rs:687:5
|
687 | / fn list_prompts(
688 ||&self,
689 || _request: Option<PaginatedRequestParams>,
690 || _cx: RequestContext<RoleServer>,
691 || ) -> impl Future<Output = Result<ListPromptsResult, ErrorData>> + Send + '_ { | |_______________________________________________________________________________^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#manual_async_fnhelp: make the function `async` and return the output of the future directly |687 ~ async fn list_prompts(688 + &self,689 + _request: Option<PaginatedRequestParams>,690 + _cx: RequestContext<RoleServer>,691 ~ ) -> Result<ListPromptsResult, ErrorData> {692 + Ok(ListPromptsResult {693 + meta: None,694 + prompts: vec![695 + Prompt::new(696 + "test_simple_prompt",697 + Some("A simple test prompt with no arguments"),698 + None,699 + ),700 + Prompt::new(701 + "test_prompt_with_arguments",702 + Some("A test prompt that accepts arguments"),703 + Some(vec![704 + PromptArgument::new("name")705 + .with_description("The name to greet")706 + .with_required(true),707 + PromptArgument::new("style")708 + .with_description("The greeting style")709 + .with_required(false),710 + ]),711 + ),712 + Prompt::new(713 + "test_prompt_with_embedded_resource",714 + Some("A test prompt that includes an embedded resource"),715 + None,716 + ),717 + Prompt::new(718 + "test_prompt_with_image",719 + Some("A test prompt that includes an image"),720 + None,721 + ),722 + ],723 + next_cursor: None,724 + })725 + } |warning: this function can be simplified using the `async fn` syntax --> conformance/src/bin/server.rs:729:5 |729 | / fn get_prompt(730 | | &self,731 | | request: GetPromptRequestParams,732 | | _cx: RequestContext<RoleServer>,733 | | ) -> impl Future<Output = Result<GetPromptResult, ErrorData>> + Send + '_ {
||_____________________________________________________________________________^
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#manual_async_fn
help: make the function`async` and return the output of the future directly
|
729 ~ async fn get_prompt(
730 + &self,
731 + request: GetPromptRequestParams,
732 + _cx: RequestContext<RoleServer>,
733 ~ ) -> Result<GetPromptResult, ErrorData> {
734 + match request.name.as_str() {
735 + "test_simple_prompt" => Ok(GetPromptResult::new(vec![PromptMessage::new_text(
736 + PromptMessageRole::User,
737 + "This is a simple test prompt.",
738 + )])
739 + .with_description("A simple test prompt")),
740 + "test_prompt_with_arguments" => {
741 + let args = request.arguments.unwrap_or_default();
742 + let name = args.get("name").and_then(|v|v.as_str()).unwrap_or("World");
743 + let style = args
744 + .get("style")
745 + .and_then(|v|v.as_str())
746 + .unwrap_or("friendly");
747 + Ok(GetPromptResult::new(vec![PromptMessage::new_text(
748 + PromptMessageRole::User,
749 + format!("Please greet {} in a {} style.", name, style),
750 + )])
751 + .with_description("A prompt with arguments"))
752 + }
753 + "test_prompt_with_embedded_resource" => Ok(GetPromptResult::new(vec![
754 + PromptMessage::new_text(PromptMessageRole::User, "Here is a resource:"),
755 + PromptMessage::new_resource(
756 + PromptMessageRole::User,
757 + "test://static-text".into(),
758 + Some("text/plain".into()),
759 + Some("Resource content for prompt".into()),
760 + None,
761 + None,
762 + None,
763 + ),
764 + ])
765 + .with_description("A prompt with an embedded resource")),
766 + "test_prompt_with_image" => {
767 + let image_content = RawImageContent {
768 + data: TEST_IMAGE_DATA.into(),
769 + mime_type: "image/png".into(),
770 + meta: None,
771 + };
772 + Ok(GetPromptResult::new(vec![
773 + PromptMessage::new_text(PromptMessageRole::User, "Here is an image:"),
774 + PromptMessage::new(
775 + PromptMessageRole::User,
776 + PromptMessageContent::Image {
777 + image: image_content.no_annotation(),
778 + },
779 + ),
780 + ])
781 + .with_description("A prompt with an image"))
782 + }
783 + _ => Err(ErrorData::invalid_params(
784 + format!("Unknown prompt: {}", request.name),
785 + None,
786 + )),
787 + }
788 + }
|
warning: this functioncan be simplified using the `async fn` syntax
--> conformance/src/bin/server.rs:792:5
|
792 | / fn complete(
793 ||&self,
794 || request: CompleteRequestParams,
795 || _cx: RequestContext<RoleServer>,
796 || ) -> impl Future<Output = Result<CompleteResult, ErrorData>> + Send + '_ { | |____________________________________________________________________________^ | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#manual_async_fnhelp: make the function `async` and return the output of the future directly |792 ~ async fn complete(793 + &self,794 + request: CompleteRequestParams,795 + _cx: RequestContext<RoleServer>,796 ~ ) -> Result<CompleteResult, ErrorData> {797 + let values = match &request.r#ref {798 + Reference::Resource(_) => {799 + if request.argument.name == "id" {800 + vec!["1".into(), "2".into(), "3".into()]801 + } else {802 + vec![]803 + }804 + }805 + Reference::Prompt(prompt_ref) => {806 + if request.argument.name == "name" {807 + vec!["Alice".into(), "Bob".into(), "Charlie".into()]808 + } else if request.argument.name == "style" {809 + vec!["friendly".into(), "formal".into(), "casual".into()]810 + } else {811 + vec![prompt_ref.name.clone()]812 + }813 + }814 + };815 + Ok(CompleteResult::new(816 + CompletionInfo::new(values).map_err(|e| ErrorData::internal_error(e, None))?,817 + ))818 + } |warning: this function can be simplified using the `async fn` syntax --> conformance/src/bin/server.rs:822:5 |822 | / fn set_level(823 | | &self,824 | | request: SetLevelRequestParams,825 | | _cx: RequestContext<RoleServer>,826 | | ) -> impl Future<Output = Result<(), ErrorData>> + Send + '_ {
||________________________________________________________________^
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#manual_async_fn
help: make the function`async` and return the output of the future directly
|
822 ~ async fn set_level(
823 + &self,
824 + request: SetLevelRequestParams,
825 + _cx: RequestContext<RoleServer>,
826 ~ ) ->Result<(), ErrorData> {
827 + let mut level = self.log_level.lock().await;
828 + *level = request.level;
829 + Ok(())
830 + }
|
warning: `mcp-conformance` (bin "conformance-server" test) generated 13 warnings (run `cargo clippy --fix --bin "conformance-server" --tests` to apply 13 suggestions)
warning: `mcp-conformance` (bin "conformance-server") generated 13 warnings (13 duplicates)
Finished `dev` profile [unoptimized + debuginfo] target(s) in 11.07s

How Has This Been Tested?

$ cargo clippy --workspace --all-targets --all-features
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.69s

Breaking Changes

No

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Documentation update

Checklist

  • I have read the MCP Documentation
  • My code follows the repository's style guidelines
  • New and existing tests pass locally
  • I have added appropriate error handling
  • I have added or updated documentation as needed

Additional context

@DaleSeoDaleSeo self-assigned this Mar 11, 2026
@github-actionsgithub-actionsBot added T-dependencies Dependencies related changes T-config Configuration file changes T-examples Example code changes T-macros Macro changes labels Mar 11, 2026
@DaleSeo
DaleSeo marked this pull request as ready for review March 11, 2026 15:55
@DaleSeo
DaleSeo requested a review from a team as a code ownerMarch 11, 2026 15:55
@alexhancock
alexhancock merged commit 8700e5c into mainMar 11, 2026
16 checks passed
@alexhancock
alexhancock deleted the chore/fix-clippy-warnings branch March 11, 2026 18:12
@github-actionsgithub-actionsBot mentioned this pull request Mar 11, 2026
@github-actionsgithub-actionsBot mentioned this pull request Mar 27, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

T-configConfiguration file changesT-dependenciesDependencies related changesT-examplesExample code changesT-macrosMacro changes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@DaleSeo@alexhancock