Skip to main content

mcpkit_rs/
model.rs

1use std::{borrow::Cow, sync::Arc};
2mod annotated;
3mod capabilities;
4mod content;
5mod elicitation_schema;
6mod extension;
7mod meta;
8mod prompt;
9mod resource;
10mod serde_impl;
11mod task;
12mod tool;
13pub use annotated::*;
14pub use capabilities::*;
15pub use content::*;
16pub use elicitation_schema::*;
17pub use extension::*;
18pub use meta::*;
19pub use prompt::*;
20pub use resource::*;
21use serde::{Deserialize, Serialize, de::DeserializeOwned};
22use serde_json::Value;
23pub use task::*;
24pub use tool::*;
25
26/// A JSON object type alias for convenient handling of JSON data.
27///
28/// You can use [`crate::object!`] or [`crate::model::object`] to create a json object quickly.
29/// This is commonly used for storing arbitrary JSON data in MCP messages.
30pub type JsonObject<F = Value> = serde_json::Map<String, F>;
31
32/// unwrap the JsonObject under [`serde_json::Value`]
33///
34/// # Panic
35/// This will panic when the value is not a object in debug mode.
36pub fn object(value: serde_json::Value) -> JsonObject {
37    debug_assert!(value.is_object());
38    match value {
39        serde_json::Value::Object(map) => map,
40        _ => JsonObject::default(),
41    }
42}
43
44/// Use this macro just like [`serde_json::json!`]
45#[cfg(feature = "macros")]
46#[cfg_attr(docsrs, doc(cfg(feature = "macros")))]
47#[macro_export]
48macro_rules! object {
49    ({$($tt:tt)*}) => {
50        $crate::model::object(serde_json::json! {
51            {$($tt)*}
52        })
53    };
54}
55
56/// This is commonly used for representing empty objects in MCP messages.
57///
58/// without returning any specific data.
59#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Copy, Eq)]
60#[serde(deny_unknown_fields)]
61#[cfg_attr(feature = "server", derive(schemars::JsonSchema))]
62pub struct EmptyObject {}
63
64pub trait ConstString: Default {
65    const VALUE: &str;
66    fn as_str(&self) -> &'static str {
67        Self::VALUE
68    }
69}
70#[macro_export]
71macro_rules! const_string {
72    ($name:ident = $value:literal) => {
73        #[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
74        pub struct $name;
75
76        impl ConstString for $name {
77            const VALUE: &str = $value;
78        }
79
80        impl serde::Serialize for $name {
81            fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
82            where
83                S: serde::Serializer,
84            {
85                $value.serialize(serializer)
86            }
87        }
88
89        impl<'de> serde::Deserialize<'de> for $name {
90            fn deserialize<D>(deserializer: D) -> Result<$name, D::Error>
91            where
92                D: serde::Deserializer<'de>,
93            {
94                let s: String = serde::Deserialize::deserialize(deserializer)?;
95                if s == $value {
96                    Ok($name)
97                } else {
98                    Err(serde::de::Error::custom(format!(concat!(
99                        "expect const string value \"",
100                        $value,
101                        "\""
102                    ))))
103                }
104            }
105        }
106
107        #[cfg(feature = "schemars")]
108        impl schemars::JsonSchema for $name {
109            fn schema_name() -> Cow<'static, str> {
110                Cow::Borrowed(stringify!($name))
111            }
112
113            fn json_schema(_: &mut schemars::SchemaGenerator) -> schemars::Schema {
114                use serde_json::{Map, json};
115
116                let mut schema_map = Map::new();
117                schema_map.insert("type".to_string(), json!("string"));
118                schema_map.insert("format".to_string(), json!("const"));
119                schema_map.insert("const".to_string(), json!($value));
120
121                schemars::Schema::from(schema_map)
122            }
123        }
124    };
125}
126
127const_string!(JsonRpcVersion2_0 = "2.0");
128
129// =============================================================================
130// CORE PROTOCOL TYPES
131// =============================================================================
132
133/// Represents the MCP protocol version used for communication.
134///
135/// This ensures compatibility between clients and servers by specifying
136/// which version of the Model Context Protocol is being used.
137#[derive(Debug, Clone, Eq, PartialEq, Hash, PartialOrd)]
138#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
139pub struct ProtocolVersion(Cow<'static, str>);
140
141impl Default for ProtocolVersion {
142    fn default() -> Self {
143        Self::LATEST
144    }
145}
146
147impl std::fmt::Display for ProtocolVersion {
148    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
149        self.0.fmt(f)
150    }
151}
152
153impl ProtocolVersion {
154    pub const V_2025_06_18: Self = Self(Cow::Borrowed("2025-06-18"));
155    pub const V_2025_03_26: Self = Self(Cow::Borrowed("2025-03-26"));
156    pub const V_2024_11_05: Self = Self(Cow::Borrowed("2024-11-05"));
157    //  Keep LATEST at 2025-03-26 until full 2025-06-18 compliance and automated testing are in place.
158    pub const LATEST: Self = Self::V_2025_03_26;
159}
160
161impl Serialize for ProtocolVersion {
162    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
163    where
164        S: serde::Serializer,
165    {
166        self.0.serialize(serializer)
167    }
168}
169
170impl<'de> Deserialize<'de> for ProtocolVersion {
171    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
172    where
173        D: serde::Deserializer<'de>,
174    {
175        let s: String = Deserialize::deserialize(deserializer)?;
176        #[allow(clippy::single_match)]
177        match s.as_str() {
178            "2024-11-05" => return Ok(ProtocolVersion::V_2024_11_05),
179            "2025-03-26" => return Ok(ProtocolVersion::V_2025_03_26),
180            "2025-06-18" => return Ok(ProtocolVersion::V_2025_06_18),
181            _ => {}
182        }
183        Ok(ProtocolVersion(Cow::Owned(s)))
184    }
185}
186
187/// A flexible identifier type that can be either a number or a string.
188///
189/// This is commonly used for request IDs and other identifiers in JSON-RPC
190/// where the specification allows both numeric and string values.
191#[derive(Debug, Clone, Eq, PartialEq, Hash)]
192pub enum NumberOrString {
193    /// A numeric identifier
194    Number(i64),
195    /// A string identifier
196    String(Arc<str>),
197}
198
199impl NumberOrString {
200    pub fn into_json_value(self) -> Value {
201        match self {
202            NumberOrString::Number(n) => Value::Number(serde_json::Number::from(n)),
203            NumberOrString::String(s) => Value::String(s.to_string()),
204        }
205    }
206}
207
208impl std::fmt::Display for NumberOrString {
209    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
210        match self {
211            NumberOrString::Number(n) => n.fmt(f),
212            NumberOrString::String(s) => s.fmt(f),
213        }
214    }
215}
216
217impl Serialize for NumberOrString {
218    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
219    where
220        S: serde::Serializer,
221    {
222        match self {
223            NumberOrString::Number(n) => n.serialize(serializer),
224            NumberOrString::String(s) => s.serialize(serializer),
225        }
226    }
227}
228
229impl<'de> Deserialize<'de> for NumberOrString {
230    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
231    where
232        D: serde::Deserializer<'de>,
233    {
234        let value: Value = Deserialize::deserialize(deserializer)?;
235        match value {
236            Value::Number(n) => {
237                if let Some(i) = n.as_i64() {
238                    Ok(NumberOrString::Number(i))
239                } else if let Some(u) = n.as_u64() {
240                    // Handle large unsigned numbers that fit in i64
241                    if u <= i64::MAX as u64 {
242                        Ok(NumberOrString::Number(u as i64))
243                    } else {
244                        Err(serde::de::Error::custom("Number too large for i64"))
245                    }
246                } else {
247                    Err(serde::de::Error::custom("Expected an integer"))
248                }
249            }
250            Value::String(s) => Ok(NumberOrString::String(s.into())),
251            _ => Err(serde::de::Error::custom("Expect number or string")),
252        }
253    }
254}
255
256#[cfg(feature = "schemars")]
257impl schemars::JsonSchema for NumberOrString {
258    fn schema_name() -> Cow<'static, str> {
259        Cow::Borrowed("NumberOrString")
260    }
261
262    fn json_schema(_: &mut schemars::SchemaGenerator) -> schemars::Schema {
263        use serde_json::{Map, json};
264
265        let mut number_schema = Map::new();
266        number_schema.insert("type".to_string(), json!("number"));
267
268        let mut string_schema = Map::new();
269        string_schema.insert("type".to_string(), json!("string"));
270
271        let mut schema_map = Map::new();
272        schema_map.insert("oneOf".to_string(), json!([number_schema, string_schema]));
273
274        schemars::Schema::from(schema_map)
275    }
276}
277
278/// Type alias for request identifiers used in JSON-RPC communication.
279pub type RequestId = NumberOrString;
280
281/// A token used to track the progress of long-running operations.
282///
283/// Progress tokens allow clients and servers to associate progress notifications
284/// with specific requests, enabling real-time updates on operation status.
285#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Hash, Eq)]
286#[serde(transparent)]
287#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
288pub struct ProgressToken(pub NumberOrString);
289
290// =============================================================================
291// JSON-RPC MESSAGE STRUCTURES
292// =============================================================================
293
294/// Represents a JSON-RPC request with method, parameters, and extensions.
295///
296/// This is the core structure for all MCP requests, containing:
297/// - `method`: The name of the method being called
298/// - `params`: The parameters for the method
299/// - `extensions`: Additional context data (similar to HTTP headers)
300#[derive(Debug, Clone, Default)]
301#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
302pub struct Request<M = String, P = JsonObject> {
303    pub method: M,
304    pub params: P,
305    /// extensions will carry anything possible in the context, including [`Meta`]
306    ///
307    /// this is similar with the Extensions in `http` crate
308    #[cfg_attr(feature = "schemars", schemars(skip))]
309    pub extensions: Extensions,
310}
311
312impl<M: Default, P> Request<M, P> {
313    pub fn new(params: P) -> Self {
314        Self {
315            method: Default::default(),
316            params,
317            extensions: Extensions::default(),
318        }
319    }
320}
321
322impl<M, P> GetExtensions for Request<M, P> {
323    fn extensions(&self) -> &Extensions {
324        &self.extensions
325    }
326    fn extensions_mut(&mut self) -> &mut Extensions {
327        &mut self.extensions
328    }
329}
330
331#[derive(Debug, Clone, Default)]
332#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
333pub struct RequestOptionalParam<M = String, P = JsonObject> {
334    pub method: M,
335    // #[serde(skip_serializing_if = "Option::is_none")]
336    pub params: Option<P>,
337    /// extensions will carry anything possible in the context, including [`Meta`]
338    ///
339    /// this is similar with the Extensions in `http` crate
340    #[cfg_attr(feature = "schemars", schemars(skip))]
341    pub extensions: Extensions,
342}
343
344impl<M: Default, P> RequestOptionalParam<M, P> {
345    pub fn with_param(params: P) -> Self {
346        Self {
347            method: Default::default(),
348            params: Some(params),
349            extensions: Extensions::default(),
350        }
351    }
352}
353
354#[derive(Debug, Clone, Default)]
355#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
356pub struct RequestNoParam<M = String> {
357    pub method: M,
358    /// extensions will carry anything possible in the context, including [`Meta`]
359    ///
360    /// this is similar with the Extensions in `http` crate
361    #[cfg_attr(feature = "schemars", schemars(skip))]
362    pub extensions: Extensions,
363}
364
365impl<M> GetExtensions for RequestNoParam<M> {
366    fn extensions(&self) -> &Extensions {
367        &self.extensions
368    }
369    fn extensions_mut(&mut self) -> &mut Extensions {
370        &mut self.extensions
371    }
372}
373#[derive(Debug, Clone, Default)]
374#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
375pub struct Notification<M = String, P = JsonObject> {
376    pub method: M,
377    pub params: P,
378    /// extensions will carry anything possible in the context, including [`Meta`]
379    ///
380    /// this is similar with the Extensions in `http` crate
381    #[cfg_attr(feature = "schemars", schemars(skip))]
382    pub extensions: Extensions,
383}
384
385impl<M: Default, P> Notification<M, P> {
386    pub fn new(params: P) -> Self {
387        Self {
388            method: Default::default(),
389            params,
390            extensions: Extensions::default(),
391        }
392    }
393}
394
395#[derive(Debug, Clone, Default)]
396#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
397pub struct NotificationNoParam<M = String> {
398    pub method: M,
399    /// extensions will carry anything possible in the context, including [`Meta`]
400    ///
401    /// this is similar with the Extensions in `http` crate
402    #[cfg_attr(feature = "schemars", schemars(skip))]
403    pub extensions: Extensions,
404}
405
406#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
407#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
408pub struct JsonRpcRequest<R = Request> {
409    pub jsonrpc: JsonRpcVersion2_0,
410    pub id: RequestId,
411    #[serde(flatten)]
412    pub request: R,
413}
414
415type DefaultResponse = JsonObject;
416#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
417#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
418pub struct JsonRpcResponse<R = JsonObject> {
419    pub jsonrpc: JsonRpcVersion2_0,
420    pub id: RequestId,
421    pub result: R,
422}
423
424#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
425#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
426pub struct JsonRpcError {
427    pub jsonrpc: JsonRpcVersion2_0,
428    pub id: RequestId,
429    pub error: ErrorData,
430}
431
432#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
433#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
434pub struct JsonRpcNotification<N = Notification> {
435    pub jsonrpc: JsonRpcVersion2_0,
436    #[serde(flatten)]
437    pub notification: N,
438}
439
440/// Standard JSON-RPC error codes used throughout the MCP protocol.
441///
442/// These codes follow the JSON-RPC 2.0 specification and provide
443/// standardized error reporting across all MCP implementations.
444#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize, PartialEq, Eq)]
445#[serde(transparent)]
446#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
447pub struct ErrorCode(pub i32);
448
449impl ErrorCode {
450    pub const RESOURCE_NOT_FOUND: Self = Self(-32002);
451    pub const INVALID_REQUEST: Self = Self(-32600);
452    pub const METHOD_NOT_FOUND: Self = Self(-32601);
453    pub const INVALID_PARAMS: Self = Self(-32602);
454    pub const INTERNAL_ERROR: Self = Self(-32603);
455    pub const PARSE_ERROR: Self = Self(-32700);
456}
457
458/// Error information for JSON-RPC error responses.
459///
460/// This structure follows the JSON-RPC 2.0 specification for error reporting,
461/// providing a standardized way to communicate errors between clients and servers.
462#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
463#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
464pub struct ErrorData {
465    /// The error type that occurred (using standard JSON-RPC error codes)
466    pub code: ErrorCode,
467
468    /// A short description of the error. The message SHOULD be limited to a concise single sentence.
469    pub message: Cow<'static, str>,
470
471    /// Additional information about the error. The value of this member is defined by the
472    /// sender (e.g. detailed error information, nested errors etc.).
473    #[serde(skip_serializing_if = "Option::is_none")]
474    pub data: Option<Value>,
475}
476
477impl ErrorData {
478    pub fn new(
479        code: ErrorCode,
480        message: impl Into<Cow<'static, str>>,
481        data: Option<Value>,
482    ) -> Self {
483        Self {
484            code,
485            message: message.into(),
486            data,
487        }
488    }
489    pub fn resource_not_found(message: impl Into<Cow<'static, str>>, data: Option<Value>) -> Self {
490        Self::new(ErrorCode::RESOURCE_NOT_FOUND, message, data)
491    }
492    pub fn parse_error(message: impl Into<Cow<'static, str>>, data: Option<Value>) -> Self {
493        Self::new(ErrorCode::PARSE_ERROR, message, data)
494    }
495    pub fn invalid_request(message: impl Into<Cow<'static, str>>, data: Option<Value>) -> Self {
496        Self::new(ErrorCode::INVALID_REQUEST, message, data)
497    }
498    pub fn method_not_found<M: ConstString>() -> Self {
499        Self::new(ErrorCode::METHOD_NOT_FOUND, M::VALUE, None)
500    }
501    pub fn invalid_params(message: impl Into<Cow<'static, str>>, data: Option<Value>) -> Self {
502        Self::new(ErrorCode::INVALID_PARAMS, message, data)
503    }
504    pub fn internal_error(message: impl Into<Cow<'static, str>>, data: Option<Value>) -> Self {
505        Self::new(ErrorCode::INTERNAL_ERROR, message, data)
506    }
507}
508
509/// Represents any JSON-RPC message that can be sent or received.
510///
511/// This enum covers all possible message types in the JSON-RPC protocol:
512/// individual requests/responses, notifications, and errors.
513/// It serves as the top-level message container for MCP communication.
514#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
515#[serde(untagged)]
516#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
517pub enum JsonRpcMessage<Req = Request, Resp = DefaultResponse, Noti = Notification> {
518    /// A single request expecting a response
519    Request(JsonRpcRequest<Req>),
520    /// A response to a previous request
521    Response(JsonRpcResponse<Resp>),
522    /// A one-way notification (no response expected)
523    Notification(JsonRpcNotification<Noti>),
524    /// An error response
525    Error(JsonRpcError),
526}
527
528impl<Req, Resp, Not> JsonRpcMessage<Req, Resp, Not> {
529    #[inline]
530    pub const fn request(request: Req, id: RequestId) -> Self {
531        JsonRpcMessage::Request(JsonRpcRequest {
532            jsonrpc: JsonRpcVersion2_0,
533            id,
534            request,
535        })
536    }
537    #[inline]
538    pub const fn response(response: Resp, id: RequestId) -> Self {
539        JsonRpcMessage::Response(JsonRpcResponse {
540            jsonrpc: JsonRpcVersion2_0,
541            id,
542            result: response,
543        })
544    }
545    #[inline]
546    pub const fn error(error: ErrorData, id: RequestId) -> Self {
547        JsonRpcMessage::Error(JsonRpcError {
548            jsonrpc: JsonRpcVersion2_0,
549            id,
550            error,
551        })
552    }
553    #[inline]
554    pub const fn notification(notification: Not) -> Self {
555        JsonRpcMessage::Notification(JsonRpcNotification {
556            jsonrpc: JsonRpcVersion2_0,
557            notification,
558        })
559    }
560    pub fn into_request(self) -> Option<(Req, RequestId)> {
561        match self {
562            JsonRpcMessage::Request(r) => Some((r.request, r.id)),
563            _ => None,
564        }
565    }
566    pub fn into_response(self) -> Option<(Resp, RequestId)> {
567        match self {
568            JsonRpcMessage::Response(r) => Some((r.result, r.id)),
569            _ => None,
570        }
571    }
572    pub fn into_notification(self) -> Option<Not> {
573        match self {
574            JsonRpcMessage::Notification(n) => Some(n.notification),
575            _ => None,
576        }
577    }
578    pub fn into_error(self) -> Option<(ErrorData, RequestId)> {
579        match self {
580            JsonRpcMessage::Error(e) => Some((e.error, e.id)),
581            _ => None,
582        }
583    }
584    pub fn into_result(self) -> Option<(Result<Resp, ErrorData>, RequestId)> {
585        match self {
586            JsonRpcMessage::Response(r) => Some((Ok(r.result), r.id)),
587            JsonRpcMessage::Error(e) => Some((Err(e.error), e.id)),
588
589            _ => None,
590        }
591    }
592}
593
594// =============================================================================
595// INITIALIZATION AND CONNECTION SETUP
596// =============================================================================
597
598/// # Empty result
599/// A response that indicates success but carries no data.
600pub type EmptyResult = EmptyObject;
601
602impl From<()> for EmptyResult {
603    fn from(_value: ()) -> Self {
604        EmptyResult {}
605    }
606}
607
608impl From<EmptyResult> for () {
609    fn from(_value: EmptyResult) {}
610}
611
612/// A catch-all response either side can use for custom requests.
613#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
614#[serde(transparent)]
615#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
616pub struct CustomResult(pub Value);
617
618impl CustomResult {
619    pub fn new(result: Value) -> Self {
620        Self(result)
621    }
622
623    /// Deserialize the result into a strongly-typed structure.
624    pub fn result_as<T: DeserializeOwned>(&self) -> Result<T, serde_json::Error> {
625        serde_json::from_value(self.0.clone())
626    }
627}
628
629#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
630#[serde(rename_all = "camelCase")]
631#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
632pub struct CancelledNotificationParam {
633    pub request_id: RequestId,
634    pub reason: Option<String>,
635}
636
637const_string!(CancelledNotificationMethod = "notifications/cancelled");
638
639/// # Cancellation
640/// This notification can be sent by either side to indicate that it is cancelling a previously-issued request.
641///
642/// The request SHOULD still be in-flight, but due to communication latency, it is always possible that this notification MAY arrive after the request has already finished.
643///
644/// This notification indicates that the result will be unused, so any associated processing SHOULD cease.
645///
646/// A client MUST NOT attempt to cancel its `initialize` request.
647pub type CancelledNotification =
648    Notification<CancelledNotificationMethod, CancelledNotificationParam>;
649
650/// A catch-all notification either side can use to send custom messages to its peer.
651///
652/// This preserves the raw `method` name and `params` payload so handlers can
653/// deserialize them into domain-specific types.
654#[derive(Debug, Clone)]
655#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
656pub struct CustomNotification {
657    pub method: String,
658    pub params: Option<Value>,
659    /// extensions will carry anything possible in the context, including [`Meta`]
660    ///
661    /// this is similar with the Extensions in `http` crate
662    #[cfg_attr(feature = "schemars", schemars(skip))]
663    pub extensions: Extensions,
664}
665
666impl CustomNotification {
667    pub fn new(method: impl Into<String>, params: Option<Value>) -> Self {
668        Self {
669            method: method.into(),
670            params,
671            extensions: Extensions::default(),
672        }
673    }
674
675    /// Deserialize `params` into a strongly-typed structure.
676    pub fn params_as<T: DeserializeOwned>(&self) -> Result<Option<T>, serde_json::Error> {
677        self.params
678            .as_ref()
679            .map(|params| serde_json::from_value(params.clone()))
680            .transpose()
681    }
682}
683
684/// A catch-all request either side can use to send custom messages to its peer.
685///
686/// This preserves the raw `method` name and `params` payload so handlers can
687/// deserialize them into domain-specific types.
688#[derive(Debug, Clone)]
689#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
690pub struct CustomRequest {
691    pub method: String,
692    pub params: Option<Value>,
693    /// extensions will carry anything possible in the context, including [`Meta`]
694    ///
695    /// this is similar with the Extensions in `http` crate
696    #[cfg_attr(feature = "schemars", schemars(skip))]
697    pub extensions: Extensions,
698}
699
700impl CustomRequest {
701    pub fn new(method: impl Into<String>, params: Option<Value>) -> Self {
702        Self {
703            method: method.into(),
704            params,
705            extensions: Extensions::default(),
706        }
707    }
708
709    /// Deserialize `params` into a strongly-typed structure.
710    pub fn params_as<T: DeserializeOwned>(&self) -> Result<Option<T>, serde_json::Error> {
711        self.params
712            .as_ref()
713            .map(|params| serde_json::from_value(params.clone()))
714            .transpose()
715    }
716}
717
718const_string!(InitializeResultMethod = "initialize");
719/// # Initialization
720/// This request is sent from the client to the server when it first connects, asking it to begin initialization.
721pub type InitializeRequest = Request<InitializeResultMethod, InitializeRequestParams>;
722
723const_string!(InitializedNotificationMethod = "notifications/initialized");
724/// This notification is sent from the client to the server after initialization has finished.
725pub type InitializedNotification = NotificationNoParam<InitializedNotificationMethod>;
726
727/// Parameters sent by a client when initializing a connection to an MCP server.
728///
729/// This contains the client's protocol version, capabilities, and implementation
730/// information, allowing the server to understand what the client supports.
731#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
732#[serde(rename_all = "camelCase")]
733#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
734pub struct InitializeRequestParams {
735    /// Protocol-level metadata for this request (SEP-1319)
736    #[serde(rename = "_meta", default, skip_serializing_if = "Option::is_none")]
737    pub meta: Option<Meta>,
738    /// The MCP protocol version this client supports
739    pub protocol_version: ProtocolVersion,
740    /// The capabilities this client supports (sampling, roots, etc.)
741    pub capabilities: ClientCapabilities,
742    /// Information about the client implementation
743    pub client_info: Implementation,
744}
745
746impl RequestParamsMeta for InitializeRequestParams {
747    fn meta(&self) -> Option<&Meta> {
748        self.meta.as_ref()
749    }
750    fn meta_mut(&mut self) -> &mut Option<Meta> {
751        &mut self.meta
752    }
753}
754
755/// Deprecated: Use [`InitializeRequestParams`] instead (SEP-1319 compliance).
756#[deprecated(since = "0.13.0", note = "Use InitializeRequestParams instead")]
757pub type InitializeRequestParam = InitializeRequestParams;
758
759/// The server's response to an initialization request.
760///
761/// Contains the server's protocol version, capabilities, and implementation
762/// information, along with optional instructions for the client.
763#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
764#[serde(rename_all = "camelCase")]
765#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
766pub struct InitializeResult {
767    /// The MCP protocol version this server supports
768    pub protocol_version: ProtocolVersion,
769    /// The capabilities this server provides (tools, resources, prompts, etc.)
770    pub capabilities: ServerCapabilities,
771    /// Information about the server implementation
772    pub server_info: Implementation,
773    /// Optional human-readable instructions about using this server
774    #[serde(skip_serializing_if = "Option::is_none")]
775    pub instructions: Option<String>,
776}
777
778pub type ServerInfo = InitializeResult;
779pub type ClientInfo = InitializeRequestParams;
780
781#[allow(clippy::derivable_impls)]
782impl Default for ServerInfo {
783    fn default() -> Self {
784        ServerInfo {
785            protocol_version: ProtocolVersion::default(),
786            capabilities: ServerCapabilities::default(),
787            server_info: Implementation::from_build_env(),
788            instructions: None,
789        }
790    }
791}
792
793#[allow(clippy::derivable_impls)]
794impl Default for ClientInfo {
795    fn default() -> Self {
796        ClientInfo {
797            meta: None,
798            protocol_version: ProtocolVersion::default(),
799            capabilities: ClientCapabilities::default(),
800            client_info: Implementation::from_build_env(),
801        }
802    }
803}
804
805/// A URL pointing to an icon resource or a base64-encoded data URI.
806///
807/// Clients that support rendering icons MUST support at least the following MIME types:
808/// - image/png - PNG images (safe, universal compatibility)
809/// - image/jpeg (and image/jpg) - JPEG images (safe, universal compatibility)
810///
811/// Clients that support rendering icons SHOULD also support:
812/// - image/svg+xml - SVG images (scalable but requires security precautions)
813/// - image/webp - WebP images (modern, efficient format)
814#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
815#[serde(rename_all = "camelCase")]
816#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
817pub struct Icon {
818    /// A standard URI pointing to an icon resource
819    pub src: String,
820    /// Optional override if the server's MIME type is missing or generic
821    #[serde(skip_serializing_if = "Option::is_none")]
822    pub mime_type: Option<String>,
823    /// Size specification, each string should be in WxH format (e.g., `\"48x48\"`, `\"96x96\"`) or `\"any\"` for scalable formats like SVG
824    #[serde(skip_serializing_if = "Option::is_none")]
825    pub sizes: Option<Vec<String>>,
826}
827
828#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
829#[serde(rename_all = "camelCase")]
830#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
831pub struct Implementation {
832    pub name: String,
833    #[serde(skip_serializing_if = "Option::is_none")]
834    pub title: Option<String>,
835    pub version: String,
836    #[serde(skip_serializing_if = "Option::is_none")]
837    pub icons: Option<Vec<Icon>>,
838    #[serde(skip_serializing_if = "Option::is_none")]
839    pub website_url: Option<String>,
840}
841
842impl Default for Implementation {
843    fn default() -> Self {
844        Self::from_build_env()
845    }
846}
847
848impl Implementation {
849    pub fn from_build_env() -> Self {
850        Implementation {
851            name: env!("CARGO_CRATE_NAME").to_owned(),
852            title: None,
853            version: env!("CARGO_PKG_VERSION").to_owned(),
854            icons: None,
855            website_url: None,
856        }
857    }
858}
859
860#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Default)]
861#[serde(rename_all = "camelCase")]
862#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
863pub struct PaginatedRequestParams {
864    /// Protocol-level metadata for this request (SEP-1319)
865    #[serde(rename = "_meta", default, skip_serializing_if = "Option::is_none")]
866    pub meta: Option<Meta>,
867    #[serde(skip_serializing_if = "Option::is_none")]
868    pub cursor: Option<String>,
869}
870
871impl RequestParamsMeta for PaginatedRequestParams {
872    fn meta(&self) -> Option<&Meta> {
873        self.meta.as_ref()
874    }
875    fn meta_mut(&mut self) -> &mut Option<Meta> {
876        &mut self.meta
877    }
878}
879
880/// Deprecated: Use [`PaginatedRequestParams`] instead (SEP-1319 compliance).
881#[deprecated(since = "0.13.0", note = "Use PaginatedRequestParams instead")]
882pub type PaginatedRequestParam = PaginatedRequestParams;
883// =============================================================================
884// PROGRESS AND PAGINATION
885// =============================================================================
886
887const_string!(PingRequestMethod = "ping");
888pub type PingRequest = RequestNoParam<PingRequestMethod>;
889
890const_string!(ProgressNotificationMethod = "notifications/progress");
891#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
892#[serde(rename_all = "camelCase")]
893#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
894pub struct ProgressNotificationParam {
895    pub progress_token: ProgressToken,
896    /// The progress thus far. This should increase every time progress is made, even if the total is unknown.
897    pub progress: f64,
898    /// Total number of items to process (or total progress required), if known
899    #[serde(skip_serializing_if = "Option::is_none")]
900    pub total: Option<f64>,
901    /// An optional message describing the current progress.
902    #[serde(skip_serializing_if = "Option::is_none")]
903    pub message: Option<String>,
904}
905
906pub type ProgressNotification = Notification<ProgressNotificationMethod, ProgressNotificationParam>;
907
908pub type Cursor = String;
909
910macro_rules! paginated_result {
911    ($t:ident {
912        $i_item: ident: $t_item: ty
913    }) => {
914        #[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Default)]
915        #[serde(rename_all = "camelCase")]
916        #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
917        pub struct $t {
918            #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
919            pub meta: Option<Meta>,
920            #[serde(skip_serializing_if = "Option::is_none")]
921            pub next_cursor: Option<Cursor>,
922            pub $i_item: $t_item,
923        }
924
925        impl $t {
926            pub fn with_all_items(
927                items: $t_item,
928            ) -> Self {
929                Self {
930                    meta: None,
931                    next_cursor: None,
932                    $i_item: items,
933                }
934            }
935        }
936    };
937}
938
939// =============================================================================
940// RESOURCE MANAGEMENT
941// =============================================================================
942
943const_string!(ListResourcesRequestMethod = "resources/list");
944/// Request to list all available resources from a server
945pub type ListResourcesRequest =
946    RequestOptionalParam<ListResourcesRequestMethod, PaginatedRequestParams>;
947
948paginated_result!(ListResourcesResult {
949    resources: Vec<Resource>
950});
951
952const_string!(ListResourceTemplatesRequestMethod = "resources/templates/list");
953/// Request to list all available resource templates from a server
954pub type ListResourceTemplatesRequest =
955    RequestOptionalParam<ListResourceTemplatesRequestMethod, PaginatedRequestParams>;
956
957paginated_result!(ListResourceTemplatesResult {
958    resource_templates: Vec<ResourceTemplate>
959});
960
961const_string!(ReadResourceRequestMethod = "resources/read");
962/// Parameters for reading a specific resource
963#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
964#[serde(rename_all = "camelCase")]
965#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
966pub struct ReadResourceRequestParams {
967    /// Protocol-level metadata for this request (SEP-1319)
968    #[serde(rename = "_meta", default, skip_serializing_if = "Option::is_none")]
969    pub meta: Option<Meta>,
970    /// The URI of the resource to read
971    pub uri: String,
972}
973
974impl RequestParamsMeta for ReadResourceRequestParams {
975    fn meta(&self) -> Option<&Meta> {
976        self.meta.as_ref()
977    }
978    fn meta_mut(&mut self) -> &mut Option<Meta> {
979        &mut self.meta
980    }
981}
982
983/// Deprecated: Use [`ReadResourceRequestParams`] instead (SEP-1319 compliance).
984#[deprecated(since = "0.13.0", note = "Use ReadResourceRequestParams instead")]
985pub type ReadResourceRequestParam = ReadResourceRequestParams;
986
987/// Result containing the contents of a read resource
988#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
989#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
990pub struct ReadResourceResult {
991    /// The actual content of the resource
992    pub contents: Vec<ResourceContents>,
993}
994
995/// Request to read a specific resource
996pub type ReadResourceRequest = Request<ReadResourceRequestMethod, ReadResourceRequestParams>;
997
998const_string!(ResourceListChangedNotificationMethod = "notifications/resources/list_changed");
999/// Notification sent when the list of available resources changes
1000pub type ResourceListChangedNotification =
1001    NotificationNoParam<ResourceListChangedNotificationMethod>;
1002
1003const_string!(SubscribeRequestMethod = "resources/subscribe");
1004/// Parameters for subscribing to resource updates
1005#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1006#[serde(rename_all = "camelCase")]
1007#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1008pub struct SubscribeRequestParams {
1009    /// Protocol-level metadata for this request (SEP-1319)
1010    #[serde(rename = "_meta", default, skip_serializing_if = "Option::is_none")]
1011    pub meta: Option<Meta>,
1012    /// The URI of the resource to subscribe to
1013    pub uri: String,
1014}
1015
1016impl RequestParamsMeta for SubscribeRequestParams {
1017    fn meta(&self) -> Option<&Meta> {
1018        self.meta.as_ref()
1019    }
1020    fn meta_mut(&mut self) -> &mut Option<Meta> {
1021        &mut self.meta
1022    }
1023}
1024
1025/// Deprecated: Use [`SubscribeRequestParams`] instead (SEP-1319 compliance).
1026#[deprecated(since = "0.13.0", note = "Use SubscribeRequestParams instead")]
1027pub type SubscribeRequestParam = SubscribeRequestParams;
1028
1029/// Request to subscribe to resource updates
1030pub type SubscribeRequest = Request<SubscribeRequestMethod, SubscribeRequestParams>;
1031
1032const_string!(UnsubscribeRequestMethod = "resources/unsubscribe");
1033/// Parameters for unsubscribing from resource updates
1034#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1035#[serde(rename_all = "camelCase")]
1036#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1037pub struct UnsubscribeRequestParams {
1038    /// Protocol-level metadata for this request (SEP-1319)
1039    #[serde(rename = "_meta", default, skip_serializing_if = "Option::is_none")]
1040    pub meta: Option<Meta>,
1041    /// The URI of the resource to unsubscribe from
1042    pub uri: String,
1043}
1044
1045impl RequestParamsMeta for UnsubscribeRequestParams {
1046    fn meta(&self) -> Option<&Meta> {
1047        self.meta.as_ref()
1048    }
1049    fn meta_mut(&mut self) -> &mut Option<Meta> {
1050        &mut self.meta
1051    }
1052}
1053
1054/// Deprecated: Use [`UnsubscribeRequestParams`] instead (SEP-1319 compliance).
1055#[deprecated(since = "0.13.0", note = "Use UnsubscribeRequestParams instead")]
1056pub type UnsubscribeRequestParam = UnsubscribeRequestParams;
1057
1058/// Request to unsubscribe from resource updates
1059pub type UnsubscribeRequest = Request<UnsubscribeRequestMethod, UnsubscribeRequestParams>;
1060
1061const_string!(ResourceUpdatedNotificationMethod = "notifications/resources/updated");
1062/// Parameters for a resource update notification
1063#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1064#[serde(rename_all = "camelCase")]
1065#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1066pub struct ResourceUpdatedNotificationParam {
1067    /// The URI of the resource that was updated
1068    pub uri: String,
1069}
1070/// Notification sent when a subscribed resource is updated
1071pub type ResourceUpdatedNotification =
1072    Notification<ResourceUpdatedNotificationMethod, ResourceUpdatedNotificationParam>;
1073
1074// =============================================================================
1075// PROMPT MANAGEMENT
1076// =============================================================================
1077
1078const_string!(ListPromptsRequestMethod = "prompts/list");
1079/// Request to list all available prompts from a server
1080pub type ListPromptsRequest =
1081    RequestOptionalParam<ListPromptsRequestMethod, PaginatedRequestParams>;
1082
1083paginated_result!(ListPromptsResult {
1084    prompts: Vec<Prompt>
1085});
1086
1087const_string!(GetPromptRequestMethod = "prompts/get");
1088/// Parameters for retrieving a specific prompt
1089#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1090#[serde(rename_all = "camelCase")]
1091#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1092pub struct GetPromptRequestParams {
1093    /// Protocol-level metadata for this request (SEP-1319)
1094    #[serde(rename = "_meta", default, skip_serializing_if = "Option::is_none")]
1095    pub meta: Option<Meta>,
1096    pub name: String,
1097    #[serde(skip_serializing_if = "Option::is_none")]
1098    pub arguments: Option<JsonObject>,
1099}
1100
1101impl RequestParamsMeta for GetPromptRequestParams {
1102    fn meta(&self) -> Option<&Meta> {
1103        self.meta.as_ref()
1104    }
1105    fn meta_mut(&mut self) -> &mut Option<Meta> {
1106        &mut self.meta
1107    }
1108}
1109
1110/// Deprecated: Use [`GetPromptRequestParams`] instead (SEP-1319 compliance).
1111#[deprecated(since = "0.13.0", note = "Use GetPromptRequestParams instead")]
1112pub type GetPromptRequestParam = GetPromptRequestParams;
1113
1114/// Request to get a specific prompt
1115pub type GetPromptRequest = Request<GetPromptRequestMethod, GetPromptRequestParams>;
1116
1117const_string!(PromptListChangedNotificationMethod = "notifications/prompts/list_changed");
1118/// Notification sent when the list of available prompts changes
1119pub type PromptListChangedNotification = NotificationNoParam<PromptListChangedNotificationMethod>;
1120
1121const_string!(ToolListChangedNotificationMethod = "notifications/tools/list_changed");
1122/// Notification sent when the list of available tools changes
1123pub type ToolListChangedNotification = NotificationNoParam<ToolListChangedNotificationMethod>;
1124
1125// =============================================================================
1126// LOGGING
1127// =============================================================================
1128
1129/// Logging levels supported by the MCP protocol
1130#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Copy)]
1131#[serde(rename_all = "lowercase")] //match spec
1132#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1133pub enum LoggingLevel {
1134    Debug,
1135    Info,
1136    Notice,
1137    Warning,
1138    Error,
1139    Critical,
1140    Alert,
1141    Emergency,
1142}
1143
1144const_string!(SetLevelRequestMethod = "logging/setLevel");
1145/// Parameters for setting the logging level
1146#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1147#[serde(rename_all = "camelCase")]
1148#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1149pub struct SetLevelRequestParams {
1150    /// Protocol-level metadata for this request (SEP-1319)
1151    #[serde(rename = "_meta", default, skip_serializing_if = "Option::is_none")]
1152    pub meta: Option<Meta>,
1153    /// The desired logging level
1154    pub level: LoggingLevel,
1155}
1156
1157impl RequestParamsMeta for SetLevelRequestParams {
1158    fn meta(&self) -> Option<&Meta> {
1159        self.meta.as_ref()
1160    }
1161    fn meta_mut(&mut self) -> &mut Option<Meta> {
1162        &mut self.meta
1163    }
1164}
1165
1166/// Deprecated: Use [`SetLevelRequestParams`] instead (SEP-1319 compliance).
1167#[deprecated(since = "0.13.0", note = "Use SetLevelRequestParams instead")]
1168pub type SetLevelRequestParam = SetLevelRequestParams;
1169
1170/// Request to set the logging level
1171pub type SetLevelRequest = Request<SetLevelRequestMethod, SetLevelRequestParams>;
1172
1173const_string!(LoggingMessageNotificationMethod = "notifications/message");
1174/// Parameters for a logging message notification
1175#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1176#[serde(rename_all = "camelCase")]
1177#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1178pub struct LoggingMessageNotificationParam {
1179    /// The severity level of this log message
1180    pub level: LoggingLevel,
1181    /// Optional logger name that generated this message
1182    #[serde(skip_serializing_if = "Option::is_none")]
1183    pub logger: Option<String>,
1184    /// The actual log data
1185    pub data: Value,
1186}
1187/// Notification containing a log message
1188pub type LoggingMessageNotification =
1189    Notification<LoggingMessageNotificationMethod, LoggingMessageNotificationParam>;
1190
1191// =============================================================================
1192// SAMPLING (LLM INTERACTION)
1193// =============================================================================
1194
1195const_string!(CreateMessageRequestMethod = "sampling/createMessage");
1196pub type CreateMessageRequest = Request<CreateMessageRequestMethod, CreateMessageRequestParams>;
1197
1198/// Represents the role of a participant in a conversation or message exchange.
1199///
1200/// Used in sampling and chat contexts to distinguish between different
1201/// types of message senders in the conversation flow.
1202#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1203#[serde(rename_all = "camelCase")]
1204#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1205pub enum Role {
1206    /// A human user or client making a request
1207    User,
1208    /// An AI assistant or server providing a response
1209    Assistant,
1210}
1211
1212/// A message in a sampling conversation, containing a role and content.
1213///
1214/// This represents a single message in a conversation flow, used primarily
1215/// in LLM sampling requests where the conversation history is important
1216/// for generating appropriate responses.
1217#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1218#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1219pub struct SamplingMessage {
1220    /// The role of the message sender (User or Assistant)
1221    pub role: Role,
1222    /// The actual content of the message (text, image, etc.)
1223    pub content: Content,
1224}
1225
1226/// Specifies how much context should be included in sampling requests.
1227///
1228/// This allows clients to control what additional context information
1229/// should be provided to the LLM when processing sampling requests.
1230#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1231#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1232pub enum ContextInclusion {
1233    /// Include context from all connected MCP servers
1234    #[serde(rename = "allServers")]
1235    AllServers,
1236    /// Include no additional context
1237    #[serde(rename = "none")]
1238    None,
1239    /// Include context only from the requesting server
1240    #[serde(rename = "thisServer")]
1241    ThisServer,
1242}
1243
1244/// Parameters for creating a message through LLM sampling.
1245///
1246/// This structure contains all the necessary information for a client to
1247/// generate an LLM response, including conversation history, model preferences,
1248/// and generation parameters.
1249///
1250/// This implements `TaskAugmentedRequestParamsMeta` as sampling requests can be
1251/// long-running and may benefit from task-based execution.
1252#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1253#[serde(rename_all = "camelCase")]
1254#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1255pub struct CreateMessageRequestParams {
1256    /// Protocol-level metadata for this request (SEP-1319)
1257    #[serde(rename = "_meta", default, skip_serializing_if = "Option::is_none")]
1258    pub meta: Option<Meta>,
1259    /// Task metadata for async task management (SEP-1319)
1260    #[serde(skip_serializing_if = "Option::is_none")]
1261    pub task: Option<JsonObject>,
1262    /// The conversation history and current messages
1263    pub messages: Vec<SamplingMessage>,
1264    /// Preferences for model selection and behavior
1265    #[serde(skip_serializing_if = "Option::is_none")]
1266    pub model_preferences: Option<ModelPreferences>,
1267    /// System prompt to guide the model's behavior
1268    #[serde(skip_serializing_if = "Option::is_none")]
1269    pub system_prompt: Option<String>,
1270    /// How much context to include from MCP servers
1271    #[serde(skip_serializing_if = "Option::is_none")]
1272    pub include_context: Option<ContextInclusion>,
1273    /// Temperature for controlling randomness (0.0 to 1.0)
1274    #[serde(skip_serializing_if = "Option::is_none")]
1275    pub temperature: Option<f32>,
1276    /// Maximum number of tokens to generate
1277    pub max_tokens: u32,
1278    /// Sequences that should stop generation
1279    #[serde(skip_serializing_if = "Option::is_none")]
1280    pub stop_sequences: Option<Vec<String>>,
1281    /// Additional metadata for the request
1282    #[serde(skip_serializing_if = "Option::is_none")]
1283    pub metadata: Option<Value>,
1284}
1285
1286impl RequestParamsMeta for CreateMessageRequestParams {
1287    fn meta(&self) -> Option<&Meta> {
1288        self.meta.as_ref()
1289    }
1290    fn meta_mut(&mut self) -> &mut Option<Meta> {
1291        &mut self.meta
1292    }
1293}
1294
1295impl TaskAugmentedRequestParamsMeta for CreateMessageRequestParams {
1296    fn task(&self) -> Option<&JsonObject> {
1297        self.task.as_ref()
1298    }
1299    fn task_mut(&mut self) -> &mut Option<JsonObject> {
1300        &mut self.task
1301    }
1302}
1303
1304/// Deprecated: Use [`CreateMessageRequestParams`] instead (SEP-1319 compliance).
1305#[deprecated(since = "0.13.0", note = "Use CreateMessageRequestParams instead")]
1306pub type CreateMessageRequestParam = CreateMessageRequestParams;
1307
1308/// Preferences for model selection and behavior in sampling requests.
1309///
1310/// This allows servers to express their preferences for which model to use
1311/// and how to balance different priorities when the client has multiple
1312/// model options available.
1313#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1314#[serde(rename_all = "camelCase")]
1315#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1316pub struct ModelPreferences {
1317    /// Specific model names or families to prefer (e.g., "claude", "gpt")
1318    #[serde(skip_serializing_if = "Option::is_none")]
1319    pub hints: Option<Vec<ModelHint>>,
1320    /// Priority for cost optimization (0.0 to 1.0, higher = prefer cheaper models)
1321    #[serde(skip_serializing_if = "Option::is_none")]
1322    pub cost_priority: Option<f32>,
1323    /// Priority for speed/latency (0.0 to 1.0, higher = prefer faster models)
1324    #[serde(skip_serializing_if = "Option::is_none")]
1325    pub speed_priority: Option<f32>,
1326    /// Priority for intelligence/capability (0.0 to 1.0, higher = prefer more capable models)
1327    #[serde(skip_serializing_if = "Option::is_none")]
1328    pub intelligence_priority: Option<f32>,
1329}
1330
1331/// A hint suggesting a preferred model name or family.
1332///
1333/// Model hints are advisory suggestions that help clients choose appropriate
1334/// models. They can be specific model names or general families like "claude" or "gpt".
1335#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1336#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1337pub struct ModelHint {
1338    /// The suggested model name or family identifier
1339    #[serde(skip_serializing_if = "Option::is_none")]
1340    pub name: Option<String>,
1341}
1342
1343// =============================================================================
1344// COMPLETION AND AUTOCOMPLETE
1345// =============================================================================
1346
1347/// Context for completion requests providing previously resolved arguments.
1348///
1349/// This enables context-aware completion where subsequent argument completions
1350/// can take into account the values of previously resolved arguments.
1351#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Default)]
1352#[serde(rename_all = "camelCase")]
1353#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1354pub struct CompletionContext {
1355    /// Previously resolved argument values that can inform completion suggestions
1356    #[serde(skip_serializing_if = "Option::is_none")]
1357    pub arguments: Option<std::collections::HashMap<String, String>>,
1358}
1359
1360impl CompletionContext {
1361    /// Create a new empty completion context
1362    pub fn new() -> Self {
1363        Self::default()
1364    }
1365
1366    /// Create a completion context with the given arguments
1367    pub fn with_arguments(arguments: std::collections::HashMap<String, String>) -> Self {
1368        Self {
1369            arguments: Some(arguments),
1370        }
1371    }
1372
1373    /// Get a specific argument value by name
1374    pub fn get_argument(&self, name: &str) -> Option<&String> {
1375        self.arguments.as_ref()?.get(name)
1376    }
1377
1378    /// Check if the context has any arguments
1379    pub fn has_arguments(&self) -> bool {
1380        self.arguments.as_ref().is_some_and(|args| !args.is_empty())
1381    }
1382
1383    /// Get all argument names
1384    pub fn argument_names(&self) -> impl Iterator<Item = &str> {
1385        self.arguments
1386            .as_ref()
1387            .into_iter()
1388            .flat_map(|args| args.keys())
1389            .map(|k| k.as_str())
1390    }
1391}
1392
1393#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1394#[serde(rename_all = "camelCase")]
1395#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1396pub struct CompleteRequestParams {
1397    /// Protocol-level metadata for this request (SEP-1319)
1398    #[serde(rename = "_meta", default, skip_serializing_if = "Option::is_none")]
1399    pub meta: Option<Meta>,
1400    pub r#ref: Reference,
1401    pub argument: ArgumentInfo,
1402    /// Optional context containing previously resolved argument values
1403    #[serde(skip_serializing_if = "Option::is_none")]
1404    pub context: Option<CompletionContext>,
1405}
1406
1407impl RequestParamsMeta for CompleteRequestParams {
1408    fn meta(&self) -> Option<&Meta> {
1409        self.meta.as_ref()
1410    }
1411    fn meta_mut(&mut self) -> &mut Option<Meta> {
1412        &mut self.meta
1413    }
1414}
1415
1416/// Deprecated: Use [`CompleteRequestParams`] instead (SEP-1319 compliance).
1417#[deprecated(since = "0.13.0", note = "Use CompleteRequestParams instead")]
1418pub type CompleteRequestParam = CompleteRequestParams;
1419
1420pub type CompleteRequest = Request<CompleteRequestMethod, CompleteRequestParams>;
1421
1422#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Default)]
1423#[serde(rename_all = "camelCase")]
1424#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1425pub struct CompletionInfo {
1426    pub values: Vec<String>,
1427    #[serde(skip_serializing_if = "Option::is_none")]
1428    pub total: Option<u32>,
1429    #[serde(skip_serializing_if = "Option::is_none")]
1430    pub has_more: Option<bool>,
1431}
1432
1433impl CompletionInfo {
1434    /// Maximum number of completion values allowed per response according to MCP specification
1435    pub const MAX_VALUES: usize = 100;
1436
1437    /// Create a new CompletionInfo with validation for maximum values
1438    pub fn new(values: Vec<String>) -> Result<Self, String> {
1439        if values.len() > Self::MAX_VALUES {
1440            return Err(format!(
1441                "Too many completion values: {} (max: {})",
1442                values.len(),
1443                Self::MAX_VALUES
1444            ));
1445        }
1446        Ok(Self {
1447            values,
1448            total: None,
1449            has_more: None,
1450        })
1451    }
1452
1453    /// Create CompletionInfo with all values and no pagination
1454    pub fn with_all_values(values: Vec<String>) -> Result<Self, String> {
1455        let completion = Self::new(values)?;
1456        Ok(Self {
1457            total: Some(completion.values.len() as u32),
1458            has_more: Some(false),
1459            ..completion
1460        })
1461    }
1462
1463    /// Create CompletionInfo with pagination information
1464    pub fn with_pagination(
1465        values: Vec<String>,
1466        total: Option<u32>,
1467        has_more: bool,
1468    ) -> Result<Self, String> {
1469        let completion = Self::new(values)?;
1470        Ok(Self {
1471            total,
1472            has_more: Some(has_more),
1473            ..completion
1474        })
1475    }
1476
1477    /// Check if this completion response indicates more results are available
1478    pub fn has_more_results(&self) -> bool {
1479        self.has_more.unwrap_or(false)
1480    }
1481
1482    /// Get the total number of available completions, if known
1483    pub fn total_available(&self) -> Option<u32> {
1484        self.total
1485    }
1486
1487    /// Validate that the completion info complies with MCP specification
1488    pub fn validate(&self) -> Result<(), String> {
1489        if self.values.len() > Self::MAX_VALUES {
1490            return Err(format!(
1491                "Too many completion values: {} (max: {})",
1492                self.values.len(),
1493                Self::MAX_VALUES
1494            ));
1495        }
1496        Ok(())
1497    }
1498}
1499
1500#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Default)]
1501#[serde(rename_all = "camelCase")]
1502#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1503pub struct CompleteResult {
1504    pub completion: CompletionInfo,
1505}
1506
1507#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1508#[serde(tag = "type")]
1509#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1510pub enum Reference {
1511    #[serde(rename = "ref/resource")]
1512    Resource(ResourceReference),
1513    #[serde(rename = "ref/prompt")]
1514    Prompt(PromptReference),
1515}
1516
1517impl Reference {
1518    /// Create a prompt reference
1519    pub fn for_prompt(name: impl Into<String>) -> Self {
1520        // Not accepting `title` currently as it'll break the API
1521        // Until further decision, keep it `None`, modify later
1522        // if required, add `title` to the API
1523        Self::Prompt(PromptReference {
1524            name: name.into(),
1525            title: None,
1526        })
1527    }
1528
1529    /// Create a resource reference
1530    pub fn for_resource(uri: impl Into<String>) -> Self {
1531        Self::Resource(ResourceReference { uri: uri.into() })
1532    }
1533
1534    /// Get the reference type as a string
1535    pub fn reference_type(&self) -> &'static str {
1536        match self {
1537            Self::Prompt(_) => "ref/prompt",
1538            Self::Resource(_) => "ref/resource",
1539        }
1540    }
1541
1542    /// Extract prompt name if this is a prompt reference
1543    pub fn as_prompt_name(&self) -> Option<&str> {
1544        match self {
1545            Self::Prompt(prompt_ref) => Some(&prompt_ref.name),
1546            _ => None,
1547        }
1548    }
1549
1550    /// Extract resource URI if this is a resource reference
1551    pub fn as_resource_uri(&self) -> Option<&str> {
1552        match self {
1553            Self::Resource(resource_ref) => Some(&resource_ref.uri),
1554            _ => None,
1555        }
1556    }
1557}
1558
1559#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1560#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1561pub struct ResourceReference {
1562    pub uri: String,
1563}
1564
1565#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1566#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1567pub struct PromptReference {
1568    pub name: String,
1569    #[serde(skip_serializing_if = "Option::is_none")]
1570    pub title: Option<String>,
1571}
1572
1573const_string!(CompleteRequestMethod = "completion/complete");
1574#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1575#[serde(rename_all = "camelCase")]
1576#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1577pub struct ArgumentInfo {
1578    pub name: String,
1579    pub value: String,
1580}
1581
1582// =============================================================================
1583// ROOTS AND WORKSPACE MANAGEMENT
1584// =============================================================================
1585
1586#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1587#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1588pub struct Root {
1589    pub uri: String,
1590    #[serde(skip_serializing_if = "Option::is_none")]
1591    pub name: Option<String>,
1592}
1593
1594const_string!(ListRootsRequestMethod = "roots/list");
1595pub type ListRootsRequest = RequestNoParam<ListRootsRequestMethod>;
1596
1597#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Default)]
1598#[serde(rename_all = "camelCase")]
1599#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1600pub struct ListRootsResult {
1601    pub roots: Vec<Root>,
1602}
1603
1604const_string!(RootsListChangedNotificationMethod = "notifications/roots/list_changed");
1605pub type RootsListChangedNotification = NotificationNoParam<RootsListChangedNotificationMethod>;
1606
1607// =============================================================================
1608// ELICITATION (INTERACTIVE USER INPUT)
1609// =============================================================================
1610
1611// Method constants for elicitation operations.
1612// Elicitation allows servers to request interactive input from users during tool execution.
1613const_string!(ElicitationCreateRequestMethod = "elicitation/create");
1614const_string!(ElicitationResponseNotificationMethod = "notifications/elicitation/response");
1615
1616/// Represents the possible actions a user can take in response to an elicitation request.
1617///
1618/// When a server requests user input through elicitation, the user can:
1619/// - Accept: Provide the requested information and continue
1620/// - Decline: Refuse to provide the information but continue the operation
1621/// - Cancel: Stop the entire operation
1622#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)]
1623#[serde(rename_all = "lowercase")]
1624#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1625pub enum ElicitationAction {
1626    /// User accepts the request and provides the requested information
1627    Accept,
1628    /// User declines to provide the information but allows the operation to continue
1629    Decline,
1630    /// User cancels the entire operation
1631    Cancel,
1632}
1633
1634/// Parameters for creating an elicitation request to gather user input.
1635///
1636/// This structure contains everything needed to request interactive input from a user:
1637/// - A human-readable message explaining what information is needed
1638/// - A type-safe schema defining the expected structure of the response
1639///
1640/// # Example
1641///
1642/// ```rust
1643/// use mcpkit_rs::model::*;
1644///
1645/// let params = CreateElicitationRequestParams {
1646///     meta: None,
1647///     message: "Please provide your email".to_string(),
1648///     requested_schema: ElicitationSchema::builder()
1649///         .required_email("email")
1650///         .build()
1651///         .unwrap(),
1652/// };
1653/// ```
1654#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1655#[serde(rename_all = "camelCase")]
1656#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1657pub struct CreateElicitationRequestParams {
1658    /// Protocol-level metadata for this request (SEP-1319)
1659    #[serde(rename = "_meta", default, skip_serializing_if = "Option::is_none")]
1660    pub meta: Option<Meta>,
1661
1662    /// Human-readable message explaining what input is needed from the user.
1663    /// This should be clear and provide sufficient context for the user to understand
1664    /// what information they need to provide.
1665    pub message: String,
1666
1667    /// Type-safe schema defining the expected structure and validation rules for the user's response.
1668    /// This enforces the MCP 2025-06-18 specification that elicitation schemas must be objects
1669    /// with primitive-typed properties.
1670    pub requested_schema: ElicitationSchema,
1671}
1672
1673impl RequestParamsMeta for CreateElicitationRequestParams {
1674    fn meta(&self) -> Option<&Meta> {
1675        self.meta.as_ref()
1676    }
1677    fn meta_mut(&mut self) -> &mut Option<Meta> {
1678        &mut self.meta
1679    }
1680}
1681
1682/// Deprecated: Use [`CreateElicitationRequestParams`] instead (SEP-1319 compliance).
1683#[deprecated(since = "0.13.0", note = "Use CreateElicitationRequestParams instead")]
1684pub type CreateElicitationRequestParam = CreateElicitationRequestParams;
1685
1686/// The result returned by a client in response to an elicitation request.
1687///
1688/// Contains the user's decision (accept/decline/cancel) and optionally their input data
1689/// if they chose to accept the request.
1690#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1691#[serde(rename_all = "camelCase")]
1692#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1693pub struct CreateElicitationResult {
1694    /// The user's decision on how to handle the elicitation request
1695    pub action: ElicitationAction,
1696
1697    /// The actual data provided by the user, if they accepted the request.
1698    /// Must conform to the JSON schema specified in the original request.
1699    /// Only present when action is Accept.
1700    #[serde(skip_serializing_if = "Option::is_none")]
1701    pub content: Option<Value>,
1702}
1703
1704/// Request type for creating an elicitation to gather user input
1705pub type CreateElicitationRequest =
1706    Request<ElicitationCreateRequestMethod, CreateElicitationRequestParams>;
1707
1708// =============================================================================
1709// TOOL EXECUTION RESULTS
1710// =============================================================================
1711
1712/// The result of a tool call operation.
1713///
1714/// Contains the content returned by the tool execution and an optional
1715/// flag indicating whether the operation resulted in an error.
1716#[derive(Debug, Serialize, Clone, PartialEq)]
1717#[serde(rename_all = "camelCase")]
1718#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1719pub struct CallToolResult {
1720    /// The content returned by the tool (text, images, etc.)
1721    pub content: Vec<Content>,
1722    /// An optional JSON object that represents the structured result of the tool call
1723    #[serde(skip_serializing_if = "Option::is_none")]
1724    pub structured_content: Option<Value>,
1725    /// Whether this result represents an error condition
1726    #[serde(skip_serializing_if = "Option::is_none")]
1727    pub is_error: Option<bool>,
1728    /// Optional protocol-level metadata for this result
1729    #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
1730    pub meta: Option<Meta>,
1731}
1732
1733impl CallToolResult {
1734    /// Create a successful tool result with unstructured content
1735    pub fn success(content: Vec<Content>) -> Self {
1736        CallToolResult {
1737            content,
1738            structured_content: None,
1739            is_error: Some(false),
1740            meta: None,
1741        }
1742    }
1743    /// Create an error tool result with unstructured content
1744    pub fn error(content: Vec<Content>) -> Self {
1745        CallToolResult {
1746            content,
1747            structured_content: None,
1748            is_error: Some(true),
1749            meta: None,
1750        }
1751    }
1752    /// Create a successful tool result with structured content
1753    ///
1754    /// # Example
1755    ///
1756    /// ```rust,ignore
1757    /// use mcpkit_rs::model::CallToolResult;
1758    /// use serde_json::json;
1759    ///
1760    /// let result = CallToolResult::structured(json!({
1761    ///     "temperature": 22.5,
1762    ///     "humidity": 65,
1763    ///     "description": "Partly cloudy"
1764    /// }));
1765    /// ```
1766    pub fn structured(value: Value) -> Self {
1767        CallToolResult {
1768            content: vec![Content::text(value.to_string())],
1769            structured_content: Some(value),
1770            is_error: Some(false),
1771            meta: None,
1772        }
1773    }
1774    /// Create an error tool result with structured content
1775    ///
1776    /// # Example
1777    ///
1778    /// ```rust,ignore
1779    /// use mcpkit_rs::model::CallToolResult;
1780    /// use serde_json::json;
1781    ///
1782    /// let result = CallToolResult::structured_error(json!({
1783    ///     "error_code": "INVALID_INPUT",
1784    ///     "message": "Temperature value out of range",
1785    ///     "details": {
1786    ///         "min": -50,
1787    ///         "max": 50,
1788    ///         "provided": 100
1789    ///     }
1790    /// }));
1791    /// ```
1792    pub fn structured_error(value: Value) -> Self {
1793        CallToolResult {
1794            content: vec![Content::text(value.to_string())],
1795            structured_content: Some(value),
1796            is_error: Some(true),
1797            meta: None,
1798        }
1799    }
1800
1801    /// Convert the `structured_content` part of response into a certain type.
1802    ///
1803    /// # About json schema validation
1804    /// Since rust is a strong type language, we don't need to do json schema validation here.
1805    ///
1806    /// But if you do have to validate the response data, you can use [`jsonschema`](https://crates.io/crates/jsonschema) crate.
1807    pub fn into_typed<T>(self) -> Result<T, serde_json::Error>
1808    where
1809        T: DeserializeOwned,
1810    {
1811        let raw_text = match (self.structured_content, &self.content.first()) {
1812            (Some(value), _) => return serde_json::from_value(value),
1813            (None, Some(contents)) => {
1814                if let Some(text) = contents.as_text() {
1815                    let text = &text.text;
1816                    Some(text)
1817                } else {
1818                    None
1819                }
1820            }
1821            (None, None) => None,
1822        };
1823        if let Some(text) = raw_text {
1824            return serde_json::from_str(text);
1825        }
1826        serde_json::from_value(serde_json::Value::Null)
1827    }
1828}
1829
1830// Custom deserialize implementation to validate mutual exclusivity
1831impl<'de> Deserialize<'de> for CallToolResult {
1832    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
1833    where
1834        D: serde::Deserializer<'de>,
1835    {
1836        #[derive(Deserialize)]
1837        #[serde(rename_all = "camelCase")]
1838        struct CallToolResultHelper {
1839            #[serde(skip_serializing_if = "Option::is_none")]
1840            content: Option<Vec<Content>>,
1841            #[serde(skip_serializing_if = "Option::is_none")]
1842            structured_content: Option<Value>,
1843            #[serde(skip_serializing_if = "Option::is_none")]
1844            is_error: Option<bool>,
1845            /// Accept `_meta` during deserialization
1846            #[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
1847            meta: Option<Meta>,
1848        }
1849
1850        let helper = CallToolResultHelper::deserialize(deserializer)?;
1851        let result = CallToolResult {
1852            content: helper.content.unwrap_or_default(),
1853            structured_content: helper.structured_content,
1854            is_error: helper.is_error,
1855            meta: helper.meta,
1856        };
1857
1858        // Validate mutual exclusivity
1859        if result.content.is_empty() && result.structured_content.is_none() {
1860            return Err(serde::de::Error::custom(
1861                "CallToolResult must have either content or structured_content",
1862            ));
1863        }
1864
1865        Ok(result)
1866    }
1867}
1868
1869const_string!(ListToolsRequestMethod = "tools/list");
1870/// Request to list all available tools from a server
1871pub type ListToolsRequest = RequestOptionalParam<ListToolsRequestMethod, PaginatedRequestParams>;
1872
1873paginated_result!(
1874    ListToolsResult {
1875        tools: Vec<Tool>
1876    }
1877);
1878
1879const_string!(CallToolRequestMethod = "tools/call");
1880/// Parameters for calling a tool provided by an MCP server.
1881///
1882/// Contains the tool name and optional arguments needed to execute
1883/// the tool operation.
1884///
1885/// This implements `TaskAugmentedRequestParamsMeta` as tool calls can be
1886/// long-running and may benefit from task-based execution.
1887#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1888#[serde(rename_all = "camelCase")]
1889#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1890pub struct CallToolRequestParams {
1891    /// Protocol-level metadata for this request (SEP-1319)
1892    #[serde(rename = "_meta", default, skip_serializing_if = "Option::is_none")]
1893    pub meta: Option<Meta>,
1894    /// The name of the tool to call
1895    pub name: Cow<'static, str>,
1896    /// Arguments to pass to the tool (must match the tool's input schema)
1897    #[serde(skip_serializing_if = "Option::is_none")]
1898    pub arguments: Option<JsonObject>,
1899    /// Task metadata for async task management (SEP-1319)
1900    #[serde(skip_serializing_if = "Option::is_none")]
1901    pub task: Option<JsonObject>,
1902}
1903
1904impl RequestParamsMeta for CallToolRequestParams {
1905    fn meta(&self) -> Option<&Meta> {
1906        self.meta.as_ref()
1907    }
1908    fn meta_mut(&mut self) -> &mut Option<Meta> {
1909        &mut self.meta
1910    }
1911}
1912
1913impl TaskAugmentedRequestParamsMeta for CallToolRequestParams {
1914    fn task(&self) -> Option<&JsonObject> {
1915        self.task.as_ref()
1916    }
1917    fn task_mut(&mut self) -> &mut Option<JsonObject> {
1918        &mut self.task
1919    }
1920}
1921
1922/// Deprecated: Use [`CallToolRequestParams`] instead (SEP-1319 compliance).
1923#[deprecated(since = "0.13.0", note = "Use CallToolRequestParams instead")]
1924pub type CallToolRequestParam = CallToolRequestParams;
1925
1926/// Request to call a specific tool
1927pub type CallToolRequest = Request<CallToolRequestMethod, CallToolRequestParams>;
1928
1929/// The result of a sampling/createMessage request containing the generated response.
1930///
1931/// This structure contains the generated message along with metadata about
1932/// how the generation was performed and why it stopped.
1933#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1934#[serde(rename_all = "camelCase")]
1935#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1936pub struct CreateMessageResult {
1937    /// The identifier of the model that generated the response
1938    pub model: String,
1939    /// The reason why generation stopped (e.g., "endTurn", "maxTokens")
1940    #[serde(skip_serializing_if = "Option::is_none")]
1941    pub stop_reason: Option<String>,
1942    /// The generated message with role and content
1943    #[serde(flatten)]
1944    pub message: SamplingMessage,
1945}
1946
1947impl CreateMessageResult {
1948    pub const STOP_REASON_END_TURN: &str = "endTurn";
1949    pub const STOP_REASON_END_SEQUENCE: &str = "stopSequence";
1950    pub const STOP_REASON_END_MAX_TOKEN: &str = "maxTokens";
1951}
1952
1953#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1954#[serde(rename_all = "camelCase")]
1955#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1956pub struct GetPromptResult {
1957    #[serde(skip_serializing_if = "Option::is_none")]
1958    pub description: Option<String>,
1959    pub messages: Vec<PromptMessage>,
1960}
1961
1962// =============================================================================
1963// TASK MANAGEMENT
1964// =============================================================================
1965
1966const_string!(GetTaskInfoMethod = "tasks/get");
1967pub type GetTaskInfoRequest = Request<GetTaskInfoMethod, GetTaskInfoParams>;
1968
1969#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1970#[serde(rename_all = "camelCase")]
1971#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1972pub struct GetTaskInfoParams {
1973    /// Protocol-level metadata for this request (SEP-1319)
1974    #[serde(rename = "_meta", default, skip_serializing_if = "Option::is_none")]
1975    pub meta: Option<Meta>,
1976    pub task_id: String,
1977}
1978
1979impl RequestParamsMeta for GetTaskInfoParams {
1980    fn meta(&self) -> Option<&Meta> {
1981        self.meta.as_ref()
1982    }
1983    fn meta_mut(&mut self) -> &mut Option<Meta> {
1984        &mut self.meta
1985    }
1986}
1987
1988/// Deprecated: Use [`GetTaskInfoParams`] instead (SEP-1319 compliance).
1989#[deprecated(since = "0.13.0", note = "Use GetTaskInfoParams instead")]
1990pub type GetTaskInfoParam = GetTaskInfoParams;
1991
1992const_string!(ListTasksMethod = "tasks/list");
1993pub type ListTasksRequest = RequestOptionalParam<ListTasksMethod, PaginatedRequestParams>;
1994
1995const_string!(GetTaskResultMethod = "tasks/result");
1996pub type GetTaskResultRequest = Request<GetTaskResultMethod, GetTaskResultParams>;
1997
1998#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
1999#[serde(rename_all = "camelCase")]
2000#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2001pub struct GetTaskResultParams {
2002    /// Protocol-level metadata for this request (SEP-1319)
2003    #[serde(rename = "_meta", default, skip_serializing_if = "Option::is_none")]
2004    pub meta: Option<Meta>,
2005    pub task_id: String,
2006}
2007
2008impl RequestParamsMeta for GetTaskResultParams {
2009    fn meta(&self) -> Option<&Meta> {
2010        self.meta.as_ref()
2011    }
2012    fn meta_mut(&mut self) -> &mut Option<Meta> {
2013        &mut self.meta
2014    }
2015}
2016
2017/// Deprecated: Use [`GetTaskResultParams`] instead (SEP-1319 compliance).
2018#[deprecated(since = "0.13.0", note = "Use GetTaskResultParams instead")]
2019pub type GetTaskResultParam = GetTaskResultParams;
2020
2021const_string!(CancelTaskMethod = "tasks/cancel");
2022pub type CancelTaskRequest = Request<CancelTaskMethod, CancelTaskParams>;
2023
2024#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
2025#[serde(rename_all = "camelCase")]
2026#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2027pub struct CancelTaskParams {
2028    /// Protocol-level metadata for this request (SEP-1319)
2029    #[serde(rename = "_meta", default, skip_serializing_if = "Option::is_none")]
2030    pub meta: Option<Meta>,
2031    pub task_id: String,
2032}
2033
2034impl RequestParamsMeta for CancelTaskParams {
2035    fn meta(&self) -> Option<&Meta> {
2036        self.meta.as_ref()
2037    }
2038    fn meta_mut(&mut self) -> &mut Option<Meta> {
2039        &mut self.meta
2040    }
2041}
2042
2043/// Deprecated: Use [`CancelTaskParams`] instead (SEP-1319 compliance).
2044#[deprecated(since = "0.13.0", note = "Use CancelTaskParams instead")]
2045pub type CancelTaskParam = CancelTaskParams;
2046#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
2047#[serde(rename_all = "camelCase")]
2048#[serde(deny_unknown_fields)]
2049#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2050pub struct GetTaskInfoResult {
2051    #[serde(skip_serializing_if = "Option::is_none")]
2052    pub task: Option<crate::model::Task>,
2053}
2054
2055#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Default)]
2056#[serde(rename_all = "camelCase")]
2057#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2058pub struct ListTasksResult {
2059    pub tasks: Vec<crate::model::Task>,
2060    #[serde(skip_serializing_if = "Option::is_none")]
2061    pub next_cursor: Option<String>,
2062    #[serde(skip_serializing_if = "Option::is_none")]
2063    pub total: Option<u64>,
2064}
2065
2066// =============================================================================
2067// MESSAGE TYPE UNIONS
2068// =============================================================================
2069
2070macro_rules! ts_union {
2071    (
2072        export type $U:ident =
2073            $($rest:tt)*
2074    ) => {
2075        ts_union!(@declare $U { $($rest)* });
2076        ts_union!(@impl_from $U { $($rest)* });
2077    };
2078    (@declare $U:ident { $($variant:tt)* }) => {
2079        ts_union!(@declare_variant $U { } {$($variant)*} );
2080    };
2081    (@declare_variant $U:ident { $($declared:tt)* } {$(|)? box $V:ident $($rest:tt)*}) => {
2082        ts_union!(@declare_variant $U { $($declared)* $V(Box<$V>), }  {$($rest)*});
2083    };
2084    (@declare_variant $U:ident { $($declared:tt)* } {$(|)? $V:ident $($rest:tt)*}) => {
2085        ts_union!(@declare_variant $U { $($declared)* $V($V), } {$($rest)*});
2086    };
2087    (@declare_variant $U:ident { $($declared:tt)* }  { ; }) => {
2088        ts_union!(@declare_end $U { $($declared)* } );
2089    };
2090    (@declare_end $U:ident { $($declared:tt)* }) => {
2091        #[derive(Debug, Serialize, Deserialize, Clone)]
2092        #[serde(untagged)]
2093        #[allow(clippy::large_enum_variant)]
2094        #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2095        pub enum $U {
2096            $($declared)*
2097        }
2098    };
2099    (@impl_from $U: ident {$(|)? box $V:ident $($rest:tt)*}) => {
2100        impl From<$V> for $U {
2101            fn from(value: $V) -> Self {
2102                $U::$V(Box::new(value))
2103            }
2104        }
2105        ts_union!(@impl_from $U {$($rest)*});
2106    };
2107    (@impl_from $U: ident {$(|)? $V:ident $($rest:tt)*}) => {
2108        impl From<$V> for $U {
2109            fn from(value: $V) -> Self {
2110                $U::$V(value)
2111            }
2112        }
2113        ts_union!(@impl_from $U {$($rest)*});
2114    };
2115    (@impl_from $U: ident  { ; }) => {};
2116    (@impl_from $U: ident  { }) => {};
2117}
2118
2119ts_union!(
2120    export type ClientRequest =
2121    | PingRequest
2122    | InitializeRequest
2123    | CompleteRequest
2124    | SetLevelRequest
2125    | GetPromptRequest
2126    | ListPromptsRequest
2127    | ListResourcesRequest
2128    | ListResourceTemplatesRequest
2129    | ReadResourceRequest
2130    | SubscribeRequest
2131    | UnsubscribeRequest
2132    | CallToolRequest
2133    | ListToolsRequest
2134    | GetTaskInfoRequest
2135    | ListTasksRequest
2136    | GetTaskResultRequest
2137    | CancelTaskRequest
2138    | CustomRequest;
2139);
2140
2141impl ClientRequest {
2142    pub fn method(&self) -> &str {
2143        match &self {
2144            ClientRequest::PingRequest(r) => r.method.as_str(),
2145            ClientRequest::InitializeRequest(r) => r.method.as_str(),
2146            ClientRequest::CompleteRequest(r) => r.method.as_str(),
2147            ClientRequest::SetLevelRequest(r) => r.method.as_str(),
2148            ClientRequest::GetPromptRequest(r) => r.method.as_str(),
2149            ClientRequest::ListPromptsRequest(r) => r.method.as_str(),
2150            ClientRequest::ListResourcesRequest(r) => r.method.as_str(),
2151            ClientRequest::ListResourceTemplatesRequest(r) => r.method.as_str(),
2152            ClientRequest::ReadResourceRequest(r) => r.method.as_str(),
2153            ClientRequest::SubscribeRequest(r) => r.method.as_str(),
2154            ClientRequest::UnsubscribeRequest(r) => r.method.as_str(),
2155            ClientRequest::CallToolRequest(r) => r.method.as_str(),
2156            ClientRequest::ListToolsRequest(r) => r.method.as_str(),
2157            ClientRequest::GetTaskInfoRequest(r) => r.method.as_str(),
2158            ClientRequest::ListTasksRequest(r) => r.method.as_str(),
2159            ClientRequest::GetTaskResultRequest(r) => r.method.as_str(),
2160            ClientRequest::CancelTaskRequest(r) => r.method.as_str(),
2161            ClientRequest::CustomRequest(r) => r.method.as_str(),
2162        }
2163    }
2164}
2165
2166ts_union!(
2167    export type ClientNotification =
2168    | CancelledNotification
2169    | ProgressNotification
2170    | InitializedNotification
2171    | RootsListChangedNotification
2172    | CustomNotification;
2173);
2174
2175ts_union!(
2176    export type ClientResult =
2177    box CreateMessageResult
2178    | ListRootsResult
2179    | CreateElicitationResult
2180    | EmptyResult
2181    | CustomResult;
2182);
2183
2184impl ClientResult {
2185    pub fn empty(_: ()) -> ClientResult {
2186        ClientResult::EmptyResult(EmptyResult {})
2187    }
2188}
2189
2190pub type ClientJsonRpcMessage = JsonRpcMessage<ClientRequest, ClientResult, ClientNotification>;
2191
2192ts_union!(
2193    export type ServerRequest =
2194    | PingRequest
2195    | CreateMessageRequest
2196    | ListRootsRequest
2197    | CreateElicitationRequest
2198    | CustomRequest;
2199);
2200
2201ts_union!(
2202    export type ServerNotification =
2203    | CancelledNotification
2204    | ProgressNotification
2205    | LoggingMessageNotification
2206    | ResourceUpdatedNotification
2207    | ResourceListChangedNotification
2208    | ToolListChangedNotification
2209    | PromptListChangedNotification
2210    | CustomNotification;
2211);
2212
2213ts_union!(
2214    export type ServerResult =
2215    | InitializeResult
2216    | CompleteResult
2217    | GetPromptResult
2218    | ListPromptsResult
2219    | ListResourcesResult
2220    | ListResourceTemplatesResult
2221    | ReadResourceResult
2222    | CallToolResult
2223    | ListToolsResult
2224    | CreateElicitationResult
2225    | EmptyResult
2226    | CreateTaskResult
2227    | ListTasksResult
2228    | GetTaskInfoResult
2229    | TaskResult
2230    | CustomResult
2231    ;
2232);
2233
2234impl ServerResult {
2235    pub fn empty(_: ()) -> ServerResult {
2236        ServerResult::EmptyResult(EmptyResult {})
2237    }
2238}
2239
2240pub type ServerJsonRpcMessage = JsonRpcMessage<ServerRequest, ServerResult, ServerNotification>;
2241
2242impl TryInto<CancelledNotification> for ServerNotification {
2243    type Error = ServerNotification;
2244    fn try_into(self) -> Result<CancelledNotification, Self::Error> {
2245        if let ServerNotification::CancelledNotification(t) = self {
2246            Ok(t)
2247        } else {
2248            Err(self)
2249        }
2250    }
2251}
2252
2253impl TryInto<CancelledNotification> for ClientNotification {
2254    type Error = ClientNotification;
2255    fn try_into(self) -> Result<CancelledNotification, Self::Error> {
2256        if let ClientNotification::CancelledNotification(t) = self {
2257            Ok(t)
2258        } else {
2259            Err(self)
2260        }
2261    }
2262}
2263
2264// =============================================================================
2265// TESTS
2266// =============================================================================
2267
2268#[cfg(test)]
2269mod tests {
2270    use serde_json::json;
2271
2272    use super::*;
2273
2274    #[test]
2275    fn test_notification_serde() {
2276        let raw = json!( {
2277            "jsonrpc": JsonRpcVersion2_0,
2278            "method": InitializedNotificationMethod,
2279        });
2280        let message: ClientJsonRpcMessage =
2281            serde_json::from_value(raw.clone()).expect("invalid notification");
2282        match &message {
2283            ClientJsonRpcMessage::Notification(JsonRpcNotification {
2284                notification: ClientNotification::InitializedNotification(_n),
2285                ..
2286            }) => {}
2287            _ => panic!("Expected Notification"),
2288        }
2289        let json = serde_json::to_value(message).expect("valid json");
2290        assert_eq!(json, raw);
2291    }
2292
2293    #[test]
2294    fn test_custom_client_notification_roundtrip() {
2295        let raw = json!( {
2296            "jsonrpc": JsonRpcVersion2_0,
2297            "method": "notifications/custom",
2298            "params": {"foo": "bar"},
2299        });
2300
2301        let message: ClientJsonRpcMessage =
2302            serde_json::from_value(raw.clone()).expect("invalid notification");
2303        match &message {
2304            ClientJsonRpcMessage::Notification(JsonRpcNotification {
2305                notification: ClientNotification::CustomNotification(notification),
2306                ..
2307            }) => {
2308                assert_eq!(notification.method, "notifications/custom");
2309                assert_eq!(
2310                    notification
2311                        .params
2312                        .as_ref()
2313                        .and_then(|p| p.get("foo"))
2314                        .expect("foo present"),
2315                    "bar"
2316                );
2317            }
2318            _ => panic!("Expected custom client notification"),
2319        }
2320
2321        let json = serde_json::to_value(message).expect("valid json");
2322        assert_eq!(json, raw);
2323    }
2324
2325    #[test]
2326    fn test_custom_server_notification_roundtrip() {
2327        let raw = json!( {
2328            "jsonrpc": JsonRpcVersion2_0,
2329            "method": "notifications/custom-server",
2330            "params": {"hello": "world"},
2331        });
2332
2333        let message: ServerJsonRpcMessage =
2334            serde_json::from_value(raw.clone()).expect("invalid notification");
2335        match &message {
2336            ServerJsonRpcMessage::Notification(JsonRpcNotification {
2337                notification: ServerNotification::CustomNotification(notification),
2338                ..
2339            }) => {
2340                assert_eq!(notification.method, "notifications/custom-server");
2341                assert_eq!(
2342                    notification
2343                        .params
2344                        .as_ref()
2345                        .and_then(|p| p.get("hello"))
2346                        .expect("hello present"),
2347                    "world"
2348                );
2349            }
2350            _ => panic!("Expected custom server notification"),
2351        }
2352
2353        let json = serde_json::to_value(message).expect("valid json");
2354        assert_eq!(json, raw);
2355    }
2356
2357    #[test]
2358    fn test_custom_request_roundtrip() {
2359        let raw = json!( {
2360            "jsonrpc": JsonRpcVersion2_0,
2361            "id": 42,
2362            "method": "requests/custom",
2363            "params": {"foo": "bar"},
2364        });
2365
2366        let message: ClientJsonRpcMessage =
2367            serde_json::from_value(raw.clone()).expect("invalid request");
2368        match &message {
2369            ClientJsonRpcMessage::Request(JsonRpcRequest { id, request, .. }) => {
2370                assert_eq!(id, &RequestId::Number(42));
2371                match request {
2372                    ClientRequest::CustomRequest(custom) => {
2373                        let expected_request = json!({
2374                            "method": "requests/custom",
2375                            "params": {"foo": "bar"},
2376                        });
2377                        let actual_request =
2378                            serde_json::to_value(custom).expect("serialize custom request");
2379                        assert_eq!(actual_request, expected_request);
2380                    }
2381                    other => panic!("Expected custom request, got: {other:?}"),
2382                }
2383            }
2384            other => panic!("Expected request, got: {other:?}"),
2385        }
2386
2387        let json = serde_json::to_value(message).expect("valid json");
2388        assert_eq!(json, raw);
2389    }
2390
2391    #[test]
2392    fn test_request_conversion() {
2393        let raw = json!( {
2394            "jsonrpc": JsonRpcVersion2_0,
2395            "id": 1,
2396            "method": "request",
2397            "params": {"key": "value"},
2398        });
2399        let message: JsonRpcMessage = serde_json::from_value(raw.clone()).expect("invalid request");
2400
2401        match &message {
2402            JsonRpcMessage::Request(r) => {
2403                assert_eq!(r.id, RequestId::Number(1));
2404                assert_eq!(r.request.method, "request");
2405                assert_eq!(
2406                    &r.request.params,
2407                    json!({"key": "value"})
2408                        .as_object()
2409                        .expect("should be an object")
2410                );
2411            }
2412            _ => panic!("Expected Request"),
2413        }
2414        let json = serde_json::to_value(&message).expect("valid json");
2415        assert_eq!(json, raw);
2416    }
2417
2418    #[test]
2419    fn test_initial_request_response_serde() {
2420        let request = json!({
2421          "jsonrpc": "2.0",
2422          "id": 1,
2423          "method": "initialize",
2424          "params": {
2425            "protocolVersion": "2024-11-05",
2426            "capabilities": {
2427              "roots": {
2428                "listChanged": true
2429              },
2430              "sampling": {}
2431            },
2432            "clientInfo": {
2433              "name": "ExampleClient",
2434              "version": "1.0.0"
2435            }
2436          }
2437        });
2438        let raw_response_json = json!({
2439          "jsonrpc": "2.0",
2440          "id": 1,
2441          "result": {
2442            "protocolVersion": "2024-11-05",
2443            "capabilities": {
2444              "logging": {},
2445              "prompts": {
2446                "listChanged": true
2447              },
2448              "resources": {
2449                "subscribe": true,
2450                "listChanged": true
2451              },
2452              "tools": {
2453                "listChanged": true
2454              }
2455            },
2456            "serverInfo": {
2457              "name": "ExampleServer",
2458              "version": "1.0.0"
2459            }
2460          }
2461        });
2462        let request: ClientJsonRpcMessage =
2463            serde_json::from_value(request.clone()).expect("invalid request");
2464        let (request, id) = request.into_request().expect("should be a request");
2465        assert_eq!(id, RequestId::Number(1));
2466        #[allow(deprecated)]
2467        match request {
2468            ClientRequest::InitializeRequest(Request {
2469                method: _,
2470                params:
2471                    InitializeRequestParam {
2472                        meta: _,
2473                        protocol_version: _,
2474                        capabilities,
2475                        client_info,
2476                    },
2477                ..
2478            }) => {
2479                assert_eq!(capabilities.roots.unwrap().list_changed, Some(true));
2480                assert_eq!(capabilities.sampling.unwrap().len(), 0);
2481                assert_eq!(client_info.name, "ExampleClient");
2482                assert_eq!(client_info.version, "1.0.0");
2483            }
2484            _ => panic!("Expected InitializeRequest"),
2485        }
2486        let server_response: ServerJsonRpcMessage =
2487            serde_json::from_value(raw_response_json.clone()).expect("invalid response");
2488        let (response, id) = server_response
2489            .clone()
2490            .into_response()
2491            .expect("expect response");
2492        assert_eq!(id, RequestId::Number(1));
2493        match response {
2494            ServerResult::InitializeResult(InitializeResult {
2495                protocol_version: _,
2496                capabilities,
2497                server_info,
2498                instructions,
2499            }) => {
2500                assert_eq!(capabilities.logging.unwrap().len(), 0);
2501                assert_eq!(capabilities.prompts.unwrap().list_changed, Some(true));
2502                assert_eq!(
2503                    capabilities.resources.as_ref().unwrap().subscribe,
2504                    Some(true)
2505                );
2506                assert_eq!(capabilities.resources.unwrap().list_changed, Some(true));
2507                assert_eq!(capabilities.tools.unwrap().list_changed, Some(true));
2508                assert_eq!(server_info.name, "ExampleServer");
2509                assert_eq!(server_info.version, "1.0.0");
2510                assert_eq!(server_info.icons, None);
2511                assert_eq!(instructions, None);
2512            }
2513            other => panic!("Expected InitializeResult, got {other:?}"),
2514        }
2515
2516        let server_response_json: Value = serde_json::to_value(&server_response).expect("msg");
2517
2518        assert_eq!(server_response_json, raw_response_json);
2519    }
2520
2521    #[test]
2522    fn test_negative_and_large_request_ids() {
2523        // Test negative ID
2524        let negative_id_json = json!({
2525            "jsonrpc": "2.0",
2526            "id": -1,
2527            "method": "test",
2528            "params": {}
2529        });
2530
2531        let message: JsonRpcMessage =
2532            serde_json::from_value(negative_id_json.clone()).expect("Should parse negative ID");
2533
2534        match &message {
2535            JsonRpcMessage::Request(r) => {
2536                assert_eq!(r.id, RequestId::Number(-1));
2537            }
2538            _ => panic!("Expected Request"),
2539        }
2540
2541        // Test roundtrip serialization
2542        let serialized = serde_json::to_value(&message).expect("Should serialize");
2543        assert_eq!(serialized, negative_id_json);
2544
2545        // Test large negative ID
2546        let large_negative_json = json!({
2547            "jsonrpc": "2.0",
2548            "id": -9007199254740991i64,  // JavaScript's MIN_SAFE_INTEGER
2549            "method": "test",
2550            "params": {}
2551        });
2552
2553        let message: JsonRpcMessage = serde_json::from_value(large_negative_json.clone())
2554            .expect("Should parse large negative ID");
2555
2556        match &message {
2557            JsonRpcMessage::Request(r) => {
2558                assert_eq!(r.id, RequestId::Number(-9007199254740991i64));
2559            }
2560            _ => panic!("Expected Request"),
2561        }
2562
2563        // Test large positive ID (JavaScript's MAX_SAFE_INTEGER)
2564        let large_positive_json = json!({
2565            "jsonrpc": "2.0",
2566            "id": 9007199254740991i64,
2567            "method": "test",
2568            "params": {}
2569        });
2570
2571        let message: JsonRpcMessage = serde_json::from_value(large_positive_json.clone())
2572            .expect("Should parse large positive ID");
2573
2574        match &message {
2575            JsonRpcMessage::Request(r) => {
2576                assert_eq!(r.id, RequestId::Number(9007199254740991i64));
2577            }
2578            _ => panic!("Expected Request"),
2579        }
2580
2581        // Test zero ID
2582        let zero_id_json = json!({
2583            "jsonrpc": "2.0",
2584            "id": 0,
2585            "method": "test",
2586            "params": {}
2587        });
2588
2589        let message: JsonRpcMessage =
2590            serde_json::from_value(zero_id_json.clone()).expect("Should parse zero ID");
2591
2592        match &message {
2593            JsonRpcMessage::Request(r) => {
2594                assert_eq!(r.id, RequestId::Number(0));
2595            }
2596            _ => panic!("Expected Request"),
2597        }
2598    }
2599
2600    #[test]
2601    fn test_protocol_version_order() {
2602        let v1 = ProtocolVersion::V_2024_11_05;
2603        let v2 = ProtocolVersion::V_2025_03_26;
2604        assert!(v1 < v2);
2605    }
2606
2607    #[test]
2608    fn test_icon_serialization() {
2609        let icon = Icon {
2610            src: "https://example.com/icon.png".to_string(),
2611            mime_type: Some("image/png".to_string()),
2612            sizes: Some(vec!["48x48".to_string()]),
2613        };
2614
2615        let json = serde_json::to_value(&icon).unwrap();
2616        assert_eq!(json["src"], "https://example.com/icon.png");
2617        assert_eq!(json["mimeType"], "image/png");
2618        assert_eq!(json["sizes"][0], "48x48");
2619
2620        // Test deserialization
2621        let deserialized: Icon = serde_json::from_value(json).unwrap();
2622        assert_eq!(deserialized, icon);
2623    }
2624
2625    #[test]
2626    fn test_icon_minimal() {
2627        let icon = Icon {
2628            src: "data:image/svg+xml;base64,PHN2Zy8+".to_string(),
2629            mime_type: None,
2630            sizes: None,
2631        };
2632
2633        let json = serde_json::to_value(&icon).unwrap();
2634        assert_eq!(json["src"], "data:image/svg+xml;base64,PHN2Zy8+");
2635        assert!(json.get("mimeType").is_none());
2636        assert!(json.get("sizes").is_none());
2637    }
2638
2639    #[test]
2640    fn test_implementation_with_icons() {
2641        let implementation = Implementation {
2642            name: "test-server".to_string(),
2643            title: Some("Test Server".to_string()),
2644            version: "1.0.0".to_string(),
2645            icons: Some(vec![
2646                Icon {
2647                    src: "https://example.com/icon.png".to_string(),
2648                    mime_type: Some("image/png".to_string()),
2649                    sizes: Some(vec!["48x48".to_string()]),
2650                },
2651                Icon {
2652                    src: "https://example.com/icon.svg".to_string(),
2653                    mime_type: Some("image/svg+xml".to_string()),
2654                    sizes: Some(vec!["any".to_string()]),
2655                },
2656            ]),
2657            website_url: Some("https://example.com".to_string()),
2658        };
2659
2660        let json = serde_json::to_value(&implementation).unwrap();
2661        assert_eq!(json["name"], "test-server");
2662        assert_eq!(json["websiteUrl"], "https://example.com");
2663        assert!(json["icons"].is_array());
2664        assert_eq!(json["icons"][0]["src"], "https://example.com/icon.png");
2665        assert_eq!(json["icons"][0]["sizes"][0], "48x48");
2666        assert_eq!(json["icons"][1]["mimeType"], "image/svg+xml");
2667        assert_eq!(json["icons"][1]["sizes"][0], "any");
2668    }
2669
2670    #[test]
2671    fn test_backward_compatibility() {
2672        // Test that old JSON without icons still deserializes correctly
2673        let old_json = json!({
2674            "name": "legacy-server",
2675            "version": "0.9.0"
2676        });
2677
2678        let implementation: Implementation = serde_json::from_value(old_json).unwrap();
2679        assert_eq!(implementation.name, "legacy-server");
2680        assert_eq!(implementation.version, "0.9.0");
2681        assert_eq!(implementation.icons, None);
2682        assert_eq!(implementation.website_url, None);
2683    }
2684
2685    #[test]
2686    fn test_initialize_with_icons() {
2687        let init_result = InitializeResult {
2688            protocol_version: ProtocolVersion::default(),
2689            capabilities: ServerCapabilities::default(),
2690            server_info: Implementation {
2691                name: "icon-server".to_string(),
2692                title: None,
2693                version: "2.0.0".to_string(),
2694                icons: Some(vec![Icon {
2695                    src: "https://example.com/server.png".to_string(),
2696                    mime_type: Some("image/png".to_string()),
2697                    sizes: Some(vec!["48x48".to_string()]),
2698                }]),
2699                website_url: Some("https://docs.example.com".to_string()),
2700            },
2701            instructions: None,
2702        };
2703
2704        let json = serde_json::to_value(&init_result).unwrap();
2705        assert!(json["serverInfo"]["icons"].is_array());
2706        assert_eq!(
2707            json["serverInfo"]["icons"][0]["src"],
2708            "https://example.com/server.png"
2709        );
2710        assert_eq!(json["serverInfo"]["icons"][0]["sizes"][0], "48x48");
2711        assert_eq!(json["serverInfo"]["websiteUrl"], "https://docs.example.com");
2712    }
2713}