turul_mcp_protocol_2025_06_18/
param_extraction.rs

1//! Parameter extraction utilities for MCP protocol
2//!
3//! This module provides unified parameter extraction from JSON-RPC RequestParams
4//! to strongly-typed MCP parameter structures, matching the pattern from the other project.
5
6use crate::traits::{Params, SerdeParamExtractor};
7
8/// Macro to implement SerdeParamExtractor for any Params type that implements Deserialize
9#[macro_export]
10macro_rules! impl_serde_extractor {
11    ($param_type:ty) => {
12        impl $crate::traits::SerdeParamExtractor<$param_type> for $param_type {
13            type Error = $crate::McpError;
14
15            fn extract_serde(
16                params: turul_mcp_json_rpc_server::RequestParams,
17            ) -> Result<$param_type, Self::Error> {
18                // Convert RequestParams to Value
19                let value = params.to_value();
20
21                // Deserialize to the target type
22                serde_json::from_value(value).map_err(|e| {
23                    $crate::McpError::InvalidParameters(format!(
24                        "Failed to deserialize {}: {}",
25                        stringify!($param_type),
26                        e
27                    ))
28                })
29            }
30        }
31    };
32}
33
34// Apply macro to all serde-compatible parameter types that exist
35// Note: InitializeRequest doesn't follow the Request/Params pattern
36impl_serde_extractor!(crate::tools::CallToolParams);
37impl_serde_extractor!(crate::tools::ListToolsParams);
38impl_serde_extractor!(crate::resources::ListResourcesParams);
39impl_serde_extractor!(crate::resources::ListResourceTemplatesParams);
40impl_serde_extractor!(crate::resources::ReadResourceParams);
41// Note: Subscribe/Unsubscribe don't have separate params types
42impl_serde_extractor!(crate::prompts::ListPromptsParams);
43impl_serde_extractor!(crate::prompts::GetPromptParams);
44impl_serde_extractor!(crate::completion::CompleteParams);
45impl_serde_extractor!(crate::logging::SetLevelParams);
46// Note: ListRootsRequest has no params per MCP spec
47// Note: ResourceTemplate functionality is now in resources module
48// ListResourceTemplatesParams is already handled above in resources section
49// GetTemplateRequest and RenderTemplateRequest were template-specific, not part of MCP spec
50impl_serde_extractor!(crate::elicitation::ElicitCreateParams);
51impl_serde_extractor!(crate::sampling::CreateMessageParams);
52impl_serde_extractor!(crate::ping::EmptyParams);
53impl_serde_extractor!(crate::resources::SubscribeParams);
54impl_serde_extractor!(crate::resources::UnsubscribeParams);
55
56/// Generic parameter extractor function that works with any type implementing SerdeParamExtractor
57pub fn extract_params<T>(
58    params: turul_mcp_json_rpc_server::RequestParams,
59) -> Result<T, crate::McpError>
60where
61    T: Params + SerdeParamExtractor<T, Error = crate::McpError>,
62{
63    T::extract_serde(params)
64}
65
66/// Helper function to extract params from Option\<RequestParams\>
67pub fn extract_optional_params<T>(
68    params: Option<turul_mcp_json_rpc_server::RequestParams>,
69) -> Result<T, crate::McpError>
70where
71    T: Params + SerdeParamExtractor<T, Error = crate::McpError> + Default,
72{
73    match params {
74        Some(p) => extract_params(p),
75        None => Ok(T::default()),
76    }
77}