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(params: turul_mcp_json_rpc_server::RequestParams) -> Result<$param_type, Self::Error> {
16                // Convert RequestParams to Value
17                let value = params.to_value();
18                
19                // Deserialize to the target type
20                serde_json::from_value(value)
21                    .map_err(|e| $crate::McpError::InvalidParameters(
22                        format!("Failed to deserialize {}: {}", stringify!($param_type), e)
23                    ))
24            }
25        }
26    };
27}
28
29// Apply macro to all serde-compatible parameter types that exist
30// Note: InitializeRequest doesn't follow the Request/Params pattern
31impl_serde_extractor!(crate::tools::CallToolParams);
32impl_serde_extractor!(crate::tools::ListToolsParams);
33impl_serde_extractor!(crate::resources::ListResourcesParams);
34impl_serde_extractor!(crate::resources::ListResourceTemplatesParams);
35impl_serde_extractor!(crate::resources::ReadResourceParams);
36// Note: Subscribe/Unsubscribe don't have separate params types
37impl_serde_extractor!(crate::prompts::ListPromptsParams);
38impl_serde_extractor!(crate::prompts::GetPromptParams);
39impl_serde_extractor!(crate::completion::CompleteParams);
40impl_serde_extractor!(crate::logging::SetLevelParams);
41// Note: ListRootsRequest has no params per MCP spec
42// Note: ResourceTemplate functionality is now in resources module
43// ListResourceTemplatesParams is already handled above in resources section
44// GetTemplateRequest and RenderTemplateRequest were template-specific, not part of MCP spec
45impl_serde_extractor!(crate::elicitation::ElicitCreateParams);
46impl_serde_extractor!(crate::sampling::CreateMessageParams);
47impl_serde_extractor!(crate::ping::EmptyParams);
48impl_serde_extractor!(crate::resources::SubscribeParams);
49impl_serde_extractor!(crate::resources::UnsubscribeParams);
50
51/// Generic parameter extractor function that works with any type implementing SerdeParamExtractor
52pub fn extract_params<T>(params: turul_mcp_json_rpc_server::RequestParams) -> Result<T, crate::McpError>
53where
54    T: Params + SerdeParamExtractor<T, Error = crate::McpError>,
55{
56    T::extract_serde(params)
57}
58
59/// Helper function to extract params from Option<RequestParams>
60pub fn extract_optional_params<T>(params: Option<turul_mcp_json_rpc_server::RequestParams>) -> Result<T, crate::McpError>
61where
62    T: Params + SerdeParamExtractor<T, Error = crate::McpError> + Default,
63{
64    match params {
65        Some(p) => extract_params(p),
66        None => Ok(T::default()),
67    }
68}