// @generated
// DO NOT EDIT THIS FILE DIRECTLY.
// Generated MCP enum variants mirror schema type names, including shared suffixes.
#![allow(clippy::enum_variant_names)]
// Run the following in the crate root to regenerate this file:
//
// ```shell
// ./generate_mcp_types.py
// ```
use serde::Deserialize;
use serde::Serialize;
use serde::de::DeserializeOwned;
use std::convert::TryFrom;

use schemars::JsonSchema;
use ts_rs::TS;

pub const MCP_SCHEMA_VERSION: &str = "2025-06-18";
pub const JSONRPC_VERSION: &str = "2.0";

/// Paired request/response types for the Model Context Protocol (MCP).
pub trait ModelContextProtocolRequest {
    const METHOD: &'static str;
    type Params: DeserializeOwned + Serialize + Send + Sync + 'static;
    type Result: DeserializeOwned + Serialize + Send + Sync + 'static;
}

/// One-way message in the Model Context Protocol (MCP).
pub trait ModelContextProtocolNotification {
    const METHOD: &'static str;
    type Params: DeserializeOwned + Serialize + Send + Sync + 'static;
}

fn default_jsonrpc() -> String {
    JSONRPC_VERSION.to_owned()
}

/// Optional annotations for the client. The client can use annotations to inform how objects are used or displayed
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema, TS)]
pub struct Annotations {
    #[serde(default, skip_serializing_if = "Option::is_none")]
    #[ts(optional)]
    pub audience: Option<Vec<Role>>,
    #[serde(
        rename = "lastModified",
        default,
        skip_serializing_if = "Option::is_none"
    )]
    #[ts(optional)]
    pub last_modified: Option<String>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    #[ts(optional)]
    pub priority: Option<f64>,
}

/// Audio provided to or from an LLM.
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema, TS)]
pub struct AudioContent {
    #[serde(default, skip_serializing_if = "Option::is_none")]
    #[ts(optional)]
    pub annotations: Option<Annotations>,
    pub data: String,
    #[serde(rename = "mimeType")]
    pub mime_type: String,
    pub r#type: String, // &'static str = "audio"
}

/// Base interface for metadata with name (identifier) and title (display name) properties.
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema, TS)]
pub struct BaseMetadata {
    pub name: String,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    #[ts(optional)]
    pub title: Option<String>,
}

#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema, TS)]
pub struct BlobResourceContents {
    pub blob: String,
    #[serde(rename = "mimeType", default, skip_serializing_if = "Option::is_none")]
    #[ts(optional)]
    pub mime_type: Option<String>,
    pub uri: String,
}

#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema, TS)]
pub struct BooleanSchema {
    #[serde(default, skip_serializing_if = "Option::is_none")]
    #[ts(optional)]
    pub default: Option<bool>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    #[ts(optional)]
    pub description: Option<String>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    #[ts(optional)]
    pub title: Option<String>,
    pub r#type: String, // &'static str = "boolean"
}

#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema, TS)]
pub enum CallToolRequest {}

impl ModelContextProtocolRequest for CallToolRequest {
    const METHOD: &'static str = "tools/call";
    type Params = CallToolRequestParams;
    type Result = CallToolResult;
}

#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema, TS)]
pub struct CallToolRequestParams {
    #[serde(default, skip_serializing_if = "Option::is_none")]
    #[ts(optional)]
    pub arguments: Option<serde_json::Value>,
    pub name: String,
}

/// The server's response to a tool call.
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema, TS)]
pub struct CallToolResult {
    pub content: Vec<ContentBlock>,
    #[serde(rename = "isError", default, skip_serializing_if = "Option::is_none")]
    #[ts(optional)]
    pub is_error: Option<bool>,
    #[serde(
        rename = "structuredContent",
        default,
        skip_serializing_if = "Option::is_none"
    )]
    #[ts(optional)]
    pub structured_content: Option<serde_json::Value>,
}

impl From<CallToolResult> for serde_json::Value {
    fn from(value: CallToolResult) -> Self {
        // Leave this as it should never fail
        #[expect(clippy::unwrap_used)]
        serde_json::to_value(value).unwrap()
    }
}

#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema, TS)]
pub enum CancelledNotification {}

impl ModelContextProtocolNotification for CancelledNotification {
    const METHOD: &'static str = "notifications/cancelled";
    type Params = CancelledNotificationParams;
}

#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema, TS)]
pub struct CancelledNotificationParams {
    #[serde(default, skip_serializing_if = "Option::is_none")]
    #[ts(optional)]
    pub reason: Option<String>,
    #[serde(rename = "requestId")]
    pub request_id: RequestId,
}

/// Capabilities a client may support. Known capabilities are defined here, in this schema, but this is not a closed set: any client can define its own, additional capabilities.
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema, TS)]
pub struct ClientCapabilities {
    #[serde(default, skip_serializing_if = "Option::is_none")]
    #[ts(optional)]
    pub elicitation: Option<serde_json::Value>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    #[ts(optional)]
    pub experimental: Option<serde_json::Value>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    #[ts(optional)]
    pub roots: Option<ClientCapabilitiesRoots>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    #[ts(optional)]
    pub sampling: Option<serde_json::Value>,
}

/// Present if the client supports listing roots.
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema, TS)]
pub struct ClientCapabilitiesRoots {
    #[serde(
        rename = "listChanged",
        default,
        skip_serializing_if = "Option::is_none"
    )]
    #[ts(optional)]
    pub list_changed: Option<bool>,
}

#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema, TS)]
#[serde(untagged)]
pub enum ClientNotification {
    CancelledNotification(CancelledNotification),
    InitializedNotification(InitializedNotification),
    ProgressNotification(ProgressNotification),
    RootsListChangedNotification(RootsListChangedNotification),
}

#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema, TS)]
#[serde(tag = "method", content = "params")]
pub enum ClientRequest {
    #[serde(rename = "initialize")]
    InitializeRequest(<InitializeRequest as ModelContextProtocolRequest>::Params),
    #[serde(rename = "ping")]
    PingRequest(<PingRequest as ModelContextProtocolRequest>::Params),
    #[serde(rename = "resources/list")]
    ListResourcesRequest(<ListResourcesRequest as ModelContextProtocolRequest>::Params),
    #[serde(rename = "resources/templates/list")]
    ListResourceTemplatesRequest(
        <ListResourceTemplatesRequest as ModelContextProtocolRequest>::Params,
    ),
    #[serde(rename = "resources/read")]
    ReadResourceRequest(<ReadResourceRequest as ModelContextProtocolRequest>::Params),
    #[serde(rename = "resources/subscribe")]
    SubscribeRequest(<SubscribeRequest as ModelContextProtocolRequest>::Params),
    #[serde(rename = "resources/unsubscribe")]
    UnsubscribeRequest(<UnsubscribeRequest as ModelContextProtocolRequest>::Params),
    #[serde(rename = "prompts/list")]
    ListPromptsRequest(<ListPromptsRequest as ModelContextProtocolRequest>::Params),
    #[serde(rename = "prompts/get")]
    GetPromptRequest(<GetPromptRequest as ModelContextProtocolRequest>::Params),
    #[serde(rename = "tools/list")]
    ListToolsRequest(<ListToolsRequest as ModelContextProtocolRequest>::Params),
    #[serde(rename = "tools/call")]
    CallToolRequest(<CallToolRequest as ModelContextProtocolRequest>::Params),
    #[serde(rename = "logging/setLevel")]
    SetLevelRequest(<SetLevelRequest as ModelContextProtocolRequest>::Params),
    #[serde(rename = "completion/complete")]
    CompleteRequest(<CompleteRequest as ModelContextProtocolRequest>::Params),
}

#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema, TS)]
#[serde(untagged)]
pub enum ClientResult {
    Result(Result),
    CreateMessageResult(CreateMessageResult),
    ListRootsResult(ListRootsResult),
    ElicitResult(ElicitResult),
}

#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema, TS)]
pub enum CompleteRequest {}

impl ModelContextProtocolRequest for CompleteRequest {
    const METHOD: &'static str = "completion/complete";
    type Params = CompleteRequestParams;
    type Result = CompleteResult;
}

#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema, TS)]
pub struct CompleteRequestParams {
    pub argument: CompleteRequestParamsArgument,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    #[ts(optional)]
    pub context: Option<CompleteRequestParamsContext>,
    pub r#ref: CompleteRequestParamsRef,
}

/// Additional, optional context for completions
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema, TS)]
pub struct CompleteRequestParamsContext {
    #[serde(default, skip_serializing_if = "Option::is_none")]
    #[ts(optional)]
    pub arguments: Option<serde_json::Value>,
}

/// The argument's information
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema, TS)]
pub struct CompleteRequestParamsArgument {
    pub name: String,
    pub value: String,
}

#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema, TS)]
#[serde(untagged)]
pub enum CompleteRequestParamsRef {
    PromptReference(PromptReference),
    ResourceTemplateReference(ResourceTemplateReference),
}

/// The server's response to a completion/complete request
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema, TS)]
pub struct CompleteResult {
    pub completion: CompleteResultCompletion,
}

#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema, TS)]
pub struct CompleteResultCompletion {
    #[serde(rename = "hasMore", default, skip_serializing_if = "Option::is_none")]
    #[ts(optional)]
    pub has_more: Option<bool>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    #[ts(optional)]
    pub total: Option<i64>,
    pub values: Vec<String>,
}

impl From<CompleteResult> for serde_json::Value {
    fn from(value: CompleteResult) -> Self {
        // Leave this as it should never fail
        #[expect(clippy::unwrap_used)]
        serde_json::to_value(value).unwrap()
    }
}

#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema, TS)]
#[serde(untagged)]
pub enum ContentBlock {
    TextContent(TextContent),
    ImageContent(ImageContent),
    AudioContent(AudioContent),
    ResourceLink(ResourceLink),
    EmbeddedResource(EmbeddedResource),
}

#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema, TS)]
pub enum CreateMessageRequest {}

impl ModelContextProtocolRequest for CreateMessageRequest {
    const METHOD: &'static str = "sampling/createMessage";
    type Params = CreateMessageRequestParams;
    type Result = CreateMessageResult;
}

#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema, TS)]
pub struct CreateMessageRequestParams {
    #[serde(
        rename = "includeContext",
        default,
        skip_serializing_if = "Option::is_none"
    )]
    #[ts(optional)]
    pub include_context: Option<String>,
    #[serde(rename = "maxTokens")]
    pub max_tokens: i64,
    pub messages: Vec<SamplingMessage>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    #[ts(optional)]
    pub metadata: Option<serde_json::Value>,
    #[serde(
        rename = "modelPreferences",
        default,
        skip_serializing_if = "Option::is_none"
    )]
    #[ts(optional)]
    pub model_preferences: Option<ModelPreferences>,
    #[serde(
        rename = "stopSequences",
        default,
        skip_serializing_if = "Option::is_none"
    )]
    #[ts(optional)]
    pub stop_sequences: Option<Vec<String>>,
    #[serde(
        rename = "systemPrompt",
        default,
        skip_serializing_if = "Option::is_none"
    )]
    #[ts(optional)]
    pub system_prompt: Option<String>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    #[ts(optional)]
    pub temperature: Option<f64>,
}

/// The client's response to a sampling/create_message request from the server. The client should inform the user before returning the sampled message, to allow them to inspect the response (human in the loop) and decide whether to allow the server to see it.
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema, TS)]
pub struct CreateMessageResult {
    pub content: CreateMessageResultContent,
    pub model: String,
    pub role: Role,
    #[serde(
        rename = "stopReason",
        default,
        skip_serializing_if = "Option::is_none"
    )]
    #[ts(optional)]
    pub stop_reason: Option<String>,
}

#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema, TS)]
#[serde(untagged)]
pub enum CreateMessageResultContent {
    TextContent(TextContent),
    ImageContent(ImageContent),
    AudioContent(AudioContent),
}

impl From<CreateMessageResult> for serde_json::Value {
    fn from(value: CreateMessageResult) -> Self {
        // Leave this as it should never fail
        #[expect(clippy::unwrap_used)]
        serde_json::to_value(value).unwrap()
    }
}

#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema, TS)]
pub struct Cursor(String);

#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema, TS)]
pub enum ElicitRequest {}

impl ModelContextProtocolRequest for ElicitRequest {
    const METHOD: &'static str = "elicitation/create";
    type Params = ElicitRequestParams;
    type Result = ElicitResult;
}

#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema, TS)]
pub struct ElicitRequestParams {
    pub message: String,
    #[serde(rename = "requestedSchema")]
    pub requested_schema: ElicitRequestParamsRequestedSchema,
}

/// A restricted subset of JSON Schema.
/// Only top-level properties are allowed, without nesting.
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema, TS)]
pub struct ElicitRequestParamsRequestedSchema {
    pub properties: serde_json::Value,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    #[ts(optional)]
    pub required: Option<Vec<String>>,
    pub r#type: String, // &'static str = "object"
}

/// The client's response to an elicitation request.
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema, TS)]
pub struct ElicitResult {
    pub action: String,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    #[ts(optional)]
    pub content: Option<serde_json::Value>,
}

impl From<ElicitResult> for serde_json::Value {
    fn from(value: ElicitResult) -> Self {
        // Leave this as it should never fail
        #[expect(clippy::unwrap_used)]
        serde_json::to_value(value).unwrap()
    }
}

/// The contents of a resource, embedded into a prompt or tool call result.
///
/// It is up to the client how best to render embedded resources for the benefit
/// of the LLM and/or the user.
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema, TS)]
pub struct EmbeddedResource {
    #[serde(default, skip_serializing_if = "Option::is_none")]
    #[ts(optional)]
    pub annotations: Option<Annotations>,
    pub resource: EmbeddedResourceResource,
    pub r#type: String, // &'static str = "resource"
}

#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema, TS)]
#[serde(untagged)]
pub enum EmbeddedResourceResource {
    TextResourceContents(TextResourceContents),
    BlobResourceContents(BlobResourceContents),
}

pub type EmptyResult = Result;

#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema, TS)]
pub struct EnumSchema {
    #[serde(default, skip_serializing_if = "Option::is_none")]
    #[ts(optional)]
    pub description: Option<String>,
    pub r#enum: Vec<String>,
    #[serde(rename = "enumNames", default, skip_serializing_if = "Option::is_none")]
    #[ts(optional)]
    pub enum_names: Option<Vec<String>>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    #[ts(optional)]
    pub title: Option<String>,
    pub r#type: String, // &'static str = "string"
}

#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema, TS)]
pub enum GetPromptRequest {}

impl ModelContextProtocolRequest for GetPromptRequest {
    const METHOD: &'static str = "prompts/get";
    type Params = GetPromptRequestParams;
    type Result = GetPromptResult;
}

#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema, TS)]
pub struct GetPromptRequestParams {
    #[serde(default, skip_serializing_if = "Option::is_none")]
    #[ts(optional)]
    pub arguments: Option<serde_json::Value>,
    pub name: String,
}

/// The server's response to a prompts/get request from the client.
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema, TS)]
pub struct GetPromptResult {
    #[serde(default, skip_serializing_if = "Option::is_none")]
    #[ts(optional)]
    pub description: Option<String>,
    pub messages: Vec<PromptMessage>,
}

impl From<GetPromptResult> for serde_json::Value {
    fn from(value: GetPromptResult) -> Self {
        // Leave this as it should never fail
        #[expect(clippy::unwrap_used)]
        serde_json::to_value(value).unwrap()
    }
}

/// An image provided to or from an LLM.
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema, TS)]
pub struct ImageContent {
    #[serde(default, skip_serializing_if = "Option::is_none")]
    #[ts(optional)]
    pub annotations: Option<Annotations>,
    pub data: String,
    #[serde(rename = "mimeType")]
    pub mime_type: String,
    pub r#type: String, // &'static str = "image"
}

/// Describes the name and version of an MCP implementation, with an optional title for UI representation.
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema, TS)]
pub struct Implementation {
    pub name: String,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    #[ts(optional)]
    pub title: Option<String>,
    pub version: String,
    // This is an extra field that the LHA MCP server sends as part of InitializeResult.
    #[serde(default, skip_serializing_if = "Option::is_none")]
    #[ts(optional)]
    pub user_agent: Option<String>,
}

#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema, TS)]
pub enum InitializeRequest {}

impl ModelContextProtocolRequest for InitializeRequest {
    const METHOD: &'static str = "initialize";
    type Params = InitializeRequestParams;
    type Result = InitializeResult;
}

#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema, TS)]
pub struct InitializeRequestParams {
    pub capabilities: ClientCapabilities,
    #[serde(rename = "clientInfo")]
    pub client_info: Implementation,
    #[serde(rename = "protocolVersion")]
    pub protocol_version: String,
}

/// After receiving an initialize request from the client, the server sends this response.
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema, TS)]
pub struct InitializeResult {
    pub capabilities: ServerCapabilities,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    #[ts(optional)]
    pub instructions: Option<String>,
    #[serde(rename = "protocolVersion")]
    pub protocol_version: String,
    #[serde(rename = "serverInfo")]
    pub server_info: Implementation,
}

impl From<InitializeResult> for serde_json::Value {
    fn from(value: InitializeResult) -> Self {
        // Leave this as it should never fail
        #[expect(clippy::unwrap_used)]
        serde_json::to_value(value).unwrap()
    }
}

#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema, TS)]
pub enum InitializedNotification {}

impl ModelContextProtocolNotification for InitializedNotification {
    const METHOD: &'static str = "notifications/initialized";
    type Params = Option<serde_json::Value>;
}

/// A response to a request that indicates an error occurred.
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema, TS)]
pub struct JSONRPCError {
    pub error: JSONRPCErrorError,
    pub id: RequestId,
    #[serde(rename = "jsonrpc", default = "default_jsonrpc")]
    pub jsonrpc: String,
}

#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema, TS)]
pub struct JSONRPCErrorError {
    pub code: i64,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    #[ts(optional)]
    pub data: Option<serde_json::Value>,
    pub message: String,
}

/// Refers to any valid JSON-RPC object that can be decoded off the wire, or encoded to be sent.
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema, TS)]
#[serde(untagged)]
pub enum JSONRPCMessage {
    Request(JSONRPCRequest),
    Notification(JSONRPCNotification),
    Response(JSONRPCResponse),
    Error(JSONRPCError),
}

/// A notification which does not expect a response.
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema, TS)]
pub struct JSONRPCNotification {
    #[serde(rename = "jsonrpc", default = "default_jsonrpc")]
    pub jsonrpc: String,
    pub method: String,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    #[ts(optional)]
    pub params: Option<serde_json::Value>,
}

/// A request that expects a response.
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema, TS)]
pub struct JSONRPCRequest {
    pub id: RequestId,
    #[serde(rename = "jsonrpc", default = "default_jsonrpc")]
    pub jsonrpc: String,
    pub method: String,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    #[ts(optional)]
    pub params: Option<serde_json::Value>,
}

/// A successful (non-error) response to a request.
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema, TS)]
pub struct JSONRPCResponse {
    pub id: RequestId,
    #[serde(rename = "jsonrpc", default = "default_jsonrpc")]
    pub jsonrpc: String,
    pub result: Result,
}

#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema, TS)]
pub enum ListPromptsRequest {}

impl ModelContextProtocolRequest for ListPromptsRequest {
    const METHOD: &'static str = "prompts/list";
    type Params = Option<ListPromptsRequestParams>;
    type Result = ListPromptsResult;
}

#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema, TS)]
pub struct ListPromptsRequestParams {
    #[serde(default, skip_serializing_if = "Option::is_none")]
    #[ts(optional)]
    pub cursor: Option<String>,
}

/// The server's response to a prompts/list request from the client.
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema, TS)]
pub struct ListPromptsResult {
    #[serde(
        rename = "nextCursor",
        default,
        skip_serializing_if = "Option::is_none"
    )]
    #[ts(optional)]
    pub next_cursor: Option<String>,
    pub prompts: Vec<Prompt>,
}

impl From<ListPromptsResult> for serde_json::Value {
    fn from(value: ListPromptsResult) -> Self {
        // Leave this as it should never fail
        #[expect(clippy::unwrap_used)]
        serde_json::to_value(value).unwrap()
    }
}

#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema, TS)]
pub enum ListResourceTemplatesRequest {}

impl ModelContextProtocolRequest for ListResourceTemplatesRequest {
    const METHOD: &'static str = "resources/templates/list";
    type Params = Option<ListResourceTemplatesRequestParams>;
    type Result = ListResourceTemplatesResult;
}

#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema, TS)]
pub struct ListResourceTemplatesRequestParams {
    #[serde(default, skip_serializing_if = "Option::is_none")]
    #[ts(optional)]
    pub cursor: Option<String>,
}

/// The server's response to a resources/templates/list request from the client.
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema, TS)]
pub struct ListResourceTemplatesResult {
    #[serde(
        rename = "nextCursor",
        default,
        skip_serializing_if = "Option::is_none"
    )]
    #[ts(optional)]
    pub next_cursor: Option<String>,
    #[serde(rename = "resourceTemplates")]
    pub resource_templates: Vec<ResourceTemplate>,
}

impl From<ListResourceTemplatesResult> for serde_json::Value {
    fn from(value: ListResourceTemplatesResult) -> Self {
        // Leave this as it should never fail
        #[expect(clippy::unwrap_used)]
        serde_json::to_value(value).unwrap()
    }
}

#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema, TS)]
pub enum ListResourcesRequest {}

impl ModelContextProtocolRequest for ListResourcesRequest {
    const METHOD: &'static str = "resources/list";
    type Params = Option<ListResourcesRequestParams>;
    type Result = ListResourcesResult;
}

#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema, TS)]
pub struct ListResourcesRequestParams {
    #[serde(default, skip_serializing_if = "Option::is_none")]
    #[ts(optional)]
    pub cursor: Option<String>,
}

/// The server's response to a resources/list request from the client.
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema, TS)]
pub struct ListResourcesResult {
    #[serde(
        rename = "nextCursor",
        default,
        skip_serializing_if = "Option::is_none"
    )]
    #[ts(optional)]
    pub next_cursor: Option<String>,
    pub resources: Vec<Resource>,
}

impl From<ListResourcesResult> for serde_json::Value {
    fn from(value: ListResourcesResult) -> Self {
        // Leave this as it should never fail
        #[expect(clippy::unwrap_used)]
        serde_json::to_value(value).unwrap()
    }
}

#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema, TS)]
pub enum ListRootsRequest {}

impl ModelContextProtocolRequest for ListRootsRequest {
    const METHOD: &'static str = "roots/list";
    type Params = Option<serde_json::Value>;
    type Result = ListRootsResult;
}

/// The client's response to a roots/list request from the server.
/// This result contains an array of Root objects, each representing a root directory
/// or file that the server can operate on.
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema, TS)]
pub struct ListRootsResult {
    pub roots: Vec<Root>,
}

impl From<ListRootsResult> for serde_json::Value {
    fn from(value: ListRootsResult) -> Self {
        // Leave this as it should never fail
        #[expect(clippy::unwrap_used)]
        serde_json::to_value(value).unwrap()
    }
}

#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema, TS)]
pub enum ListToolsRequest {}

impl ModelContextProtocolRequest for ListToolsRequest {
    const METHOD: &'static str = "tools/list";
    type Params = Option<ListToolsRequestParams>;
    type Result = ListToolsResult;
}

#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema, TS)]
pub struct ListToolsRequestParams {
    #[serde(default, skip_serializing_if = "Option::is_none")]
    #[ts(optional)]
    pub cursor: Option<String>,
}

/// The server's response to a tools/list request from the client.
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema, TS)]
pub struct ListToolsResult {
    #[serde(
        rename = "nextCursor",
        default,
        skip_serializing_if = "Option::is_none"
    )]
    #[ts(optional)]
    pub next_cursor: Option<String>,
    pub tools: Vec<Tool>,
}

impl From<ListToolsResult> for serde_json::Value {
    fn from(value: ListToolsResult) -> Self {
        // Leave this as it should never fail
        #[expect(clippy::unwrap_used)]
        serde_json::to_value(value).unwrap()
    }
}

/// The severity of a log message.
///
/// These map to syslog message severities, as specified in RFC-5424:
/// https://datatracker.ietf.org/doc/html/rfc5424#section-6.2.1
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema, TS)]
pub enum LoggingLevel {
    #[serde(rename = "alert")]
    Alert,
    #[serde(rename = "critical")]
    Critical,
    #[serde(rename = "debug")]
    Debug,
    #[serde(rename = "emergency")]
    Emergency,
    #[serde(rename = "error")]
    Error,
    #[serde(rename = "info")]
    Info,
    #[serde(rename = "notice")]
    Notice,
    #[serde(rename = "warning")]
    Warning,
}

#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema, TS)]
pub enum LoggingMessageNotification {}

impl ModelContextProtocolNotification for LoggingMessageNotification {
    const METHOD: &'static str = "notifications/message";
    type Params = LoggingMessageNotificationParams;
}

#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema, TS)]
pub struct LoggingMessageNotificationParams {
    pub data: serde_json::Value,
    pub level: LoggingLevel,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    #[ts(optional)]
    pub logger: Option<String>,
}

/// Hints to use for model selection.
///
/// Keys not declared here are currently left unspecified by the spec and are up
/// to the client to interpret.
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema, TS)]
pub struct ModelHint {
    #[serde(default, skip_serializing_if = "Option::is_none")]
    #[ts(optional)]
    pub name: Option<String>,
}

/// The server's preferences for model selection, requested of the client during sampling.
///
/// Because LLMs can vary along multiple dimensions, choosing the "best" model is
/// rarely straightforward.  Different models excel in different areas—some are
/// faster but less capable, others are more capable but more expensive, and so
/// on. This interface allows servers to express their priorities across multiple
/// dimensions to help clients make an appropriate selection for their use case.
///
/// These preferences are always advisory. The client MAY ignore them. It is also
/// up to the client to decide how to interpret these preferences and how to
/// balance them against other considerations.
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema, TS)]
pub struct ModelPreferences {
    #[serde(
        rename = "costPriority",
        default,
        skip_serializing_if = "Option::is_none"
    )]
    #[ts(optional)]
    pub cost_priority: Option<f64>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    #[ts(optional)]
    pub hints: Option<Vec<ModelHint>>,
    #[serde(
        rename = "intelligencePriority",
        default,
        skip_serializing_if = "Option::is_none"
    )]
    #[ts(optional)]
    pub intelligence_priority: Option<f64>,
    #[serde(
        rename = "speedPriority",
        default,
        skip_serializing_if = "Option::is_none"
    )]
    #[ts(optional)]
    pub speed_priority: Option<f64>,
}

#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema, TS)]
pub struct Notification {
    pub method: String,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    #[ts(optional)]
    pub params: Option<serde_json::Value>,
}

#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema, TS)]
pub struct NumberSchema {
    #[serde(default, skip_serializing_if = "Option::is_none")]
    #[ts(optional)]
    pub description: Option<String>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    #[ts(optional)]
    pub maximum: Option<i64>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    #[ts(optional)]
    pub minimum: Option<i64>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    #[ts(optional)]
    pub title: Option<String>,
    pub r#type: String,
}

#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema, TS)]
pub struct PaginatedRequest {
    pub method: String,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    #[ts(optional)]
    pub params: Option<PaginatedRequestParams>,
}

#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema, TS)]
pub struct PaginatedRequestParams {
    #[serde(default, skip_serializing_if = "Option::is_none")]
    #[ts(optional)]
    pub cursor: Option<String>,
}

#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema, TS)]
pub struct PaginatedResult {
    #[serde(
        rename = "nextCursor",
        default,
        skip_serializing_if = "Option::is_none"
    )]
    #[ts(optional)]
    pub next_cursor: Option<String>,
}

impl From<PaginatedResult> for serde_json::Value {
    fn from(value: PaginatedResult) -> Self {
        // Leave this as it should never fail
        #[expect(clippy::unwrap_used)]
        serde_json::to_value(value).unwrap()
    }
}

#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema, TS)]
pub enum PingRequest {}

impl ModelContextProtocolRequest for PingRequest {
    const METHOD: &'static str = "ping";
    type Params = Option<serde_json::Value>;
    type Result = Result;
}

/// Restricted schema definitions that only allow primitive types
/// without nested objects or arrays.
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema, TS)]
#[serde(untagged)]
pub enum PrimitiveSchemaDefinition {
    StringSchema(StringSchema),
    NumberSchema(NumberSchema),
    BooleanSchema(BooleanSchema),
    EnumSchema(EnumSchema),
}

#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema, TS)]
pub enum ProgressNotification {}

impl ModelContextProtocolNotification for ProgressNotification {
    const METHOD: &'static str = "notifications/progress";
    type Params = ProgressNotificationParams;
}

#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema, TS)]
pub struct ProgressNotificationParams {
    #[serde(default, skip_serializing_if = "Option::is_none")]
    #[ts(optional)]
    pub message: Option<String>,
    pub progress: f64,
    #[serde(rename = "progressToken")]
    pub progress_token: ProgressToken,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    #[ts(optional)]
    pub total: Option<f64>,
}

#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, Hash, Eq, JsonSchema, TS)]
#[serde(untagged)]
pub enum ProgressToken {
    String(String),
    Integer(i64),
}

/// A prompt or prompt template that the server offers.
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema, TS)]
pub struct Prompt {
    #[serde(default, skip_serializing_if = "Option::is_none")]
    #[ts(optional)]
    pub arguments: Option<Vec<PromptArgument>>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    #[ts(optional)]
    pub description: Option<String>,
    pub name: String,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    #[ts(optional)]
    pub title: Option<String>,
}

/// Describes an argument that a prompt can accept.
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema, TS)]
pub struct PromptArgument {
    #[serde(default, skip_serializing_if = "Option::is_none")]
    #[ts(optional)]
    pub description: Option<String>,
    pub name: String,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    #[ts(optional)]
    pub required: Option<bool>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    #[ts(optional)]
    pub title: Option<String>,
}

#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema, TS)]
pub enum PromptListChangedNotification {}

impl ModelContextProtocolNotification for PromptListChangedNotification {
    const METHOD: &'static str = "notifications/prompts/list_changed";
    type Params = Option<serde_json::Value>;
}

/// Describes a message returned as part of a prompt.
///
/// This is similar to `SamplingMessage`, but also supports the embedding of
/// resources from the MCP server.
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema, TS)]
pub struct PromptMessage {
    pub content: ContentBlock,
    pub role: Role,
}

/// Identifies a prompt.
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema, TS)]
pub struct PromptReference {
    pub name: String,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    #[ts(optional)]
    pub title: Option<String>,
    pub r#type: String, // &'static str = "ref/prompt"
}

#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema, TS)]
pub enum ReadResourceRequest {}

impl ModelContextProtocolRequest for ReadResourceRequest {
    const METHOD: &'static str = "resources/read";
    type Params = ReadResourceRequestParams;
    type Result = ReadResourceResult;
}

#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema, TS)]
pub struct ReadResourceRequestParams {
    pub uri: String,
}

/// The server's response to a resources/read request from the client.
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema, TS)]
pub struct ReadResourceResult {
    pub contents: Vec<ReadResourceResultContents>,
}

#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema, TS)]
#[serde(untagged)]
pub enum ReadResourceResultContents {
    TextResourceContents(TextResourceContents),
    BlobResourceContents(BlobResourceContents),
}

impl From<ReadResourceResult> for serde_json::Value {
    fn from(value: ReadResourceResult) -> Self {
        // Leave this as it should never fail
        #[expect(clippy::unwrap_used)]
        serde_json::to_value(value).unwrap()
    }
}

#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema, TS)]
pub struct Request {
    pub method: String,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    #[ts(optional)]
    pub params: Option<serde_json::Value>,
}

#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, Hash, Eq, JsonSchema, TS)]
#[serde(untagged)]
pub enum RequestId {
    String(String),
    Integer(i64),
}

/// A known resource that the server is capable of reading.
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema, TS)]
pub struct Resource {
    #[serde(default, skip_serializing_if = "Option::is_none")]
    #[ts(optional)]
    pub annotations: Option<Annotations>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    #[ts(optional)]
    pub description: Option<String>,
    #[serde(rename = "mimeType", default, skip_serializing_if = "Option::is_none")]
    #[ts(optional)]
    pub mime_type: Option<String>,
    pub name: String,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    #[ts(optional)]
    pub size: Option<i64>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    #[ts(optional)]
    pub title: Option<String>,
    pub uri: String,
}

/// The contents of a specific resource or sub-resource.
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema, TS)]
pub struct ResourceContents {
    #[serde(rename = "mimeType", default, skip_serializing_if = "Option::is_none")]
    #[ts(optional)]
    pub mime_type: Option<String>,
    pub uri: String,
}

/// A resource that the server is capable of reading, included in a prompt or tool call result.
///
/// Note: resource links returned by tools are not guaranteed to appear in the results of `resources/list` requests.
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema, TS)]
pub struct ResourceLink {
    #[serde(default, skip_serializing_if = "Option::is_none")]
    #[ts(optional)]
    pub annotations: Option<Annotations>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    #[ts(optional)]
    pub description: Option<String>,
    #[serde(rename = "mimeType", default, skip_serializing_if = "Option::is_none")]
    #[ts(optional)]
    pub mime_type: Option<String>,
    pub name: String,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    #[ts(optional)]
    pub size: Option<i64>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    #[ts(optional)]
    pub title: Option<String>,
    pub r#type: String, // &'static str = "resource_link"
    pub uri: String,
}

#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema, TS)]
pub enum ResourceListChangedNotification {}

impl ModelContextProtocolNotification for ResourceListChangedNotification {
    const METHOD: &'static str = "notifications/resources/list_changed";
    type Params = Option<serde_json::Value>;
}

/// A template description for resources available on the server.
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema, TS)]
pub struct ResourceTemplate {
    #[serde(default, skip_serializing_if = "Option::is_none")]
    #[ts(optional)]
    pub annotations: Option<Annotations>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    #[ts(optional)]
    pub description: Option<String>,
    #[serde(rename = "mimeType", default, skip_serializing_if = "Option::is_none")]
    #[ts(optional)]
    pub mime_type: Option<String>,
    pub name: String,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    #[ts(optional)]
    pub title: Option<String>,
    #[serde(rename = "uriTemplate")]
    pub uri_template: String,
}

/// A reference to a resource or resource template definition.
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema, TS)]
pub struct ResourceTemplateReference {
    pub r#type: String, // &'static str = "ref/resource"
    pub uri: String,
}

#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema, TS)]
pub enum ResourceUpdatedNotification {}

impl ModelContextProtocolNotification for ResourceUpdatedNotification {
    const METHOD: &'static str = "notifications/resources/updated";
    type Params = ResourceUpdatedNotificationParams;
}

#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema, TS)]
pub struct ResourceUpdatedNotificationParams {
    pub uri: String,
}

pub type Result = serde_json::Value;

/// The sender or recipient of messages and data in a conversation.
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema, TS)]
pub enum Role {
    #[serde(rename = "assistant")]
    Assistant,
    #[serde(rename = "user")]
    User,
}

/// Represents a root directory or file that the server can operate on.
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema, TS)]
pub struct Root {
    #[serde(default, skip_serializing_if = "Option::is_none")]
    #[ts(optional)]
    pub name: Option<String>,
    pub uri: String,
}

#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema, TS)]
pub enum RootsListChangedNotification {}

impl ModelContextProtocolNotification for RootsListChangedNotification {
    const METHOD: &'static str = "notifications/roots/list_changed";
    type Params = Option<serde_json::Value>;
}

/// Describes a message issued to or received from an LLM API.
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema, TS)]
pub struct SamplingMessage {
    pub content: SamplingMessageContent,
    pub role: Role,
}

#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema, TS)]
#[serde(untagged)]
pub enum SamplingMessageContent {
    TextContent(TextContent),
    ImageContent(ImageContent),
    AudioContent(AudioContent),
}

/// Capabilities that a server may support. Known capabilities are defined here, in this schema, but this is not a closed set: any server can define its own, additional capabilities.
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema, TS)]
pub struct ServerCapabilities {
    #[serde(default, skip_serializing_if = "Option::is_none")]
    #[ts(optional)]
    pub completions: Option<serde_json::Value>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    #[ts(optional)]
    pub experimental: Option<serde_json::Value>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    #[ts(optional)]
    pub logging: Option<serde_json::Value>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    #[ts(optional)]
    pub prompts: Option<ServerCapabilitiesPrompts>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    #[ts(optional)]
    pub resources: Option<ServerCapabilitiesResources>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    #[ts(optional)]
    pub tools: Option<ServerCapabilitiesTools>,
}

/// Present if the server offers any tools to call.
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema, TS)]
pub struct ServerCapabilitiesTools {
    #[serde(
        rename = "listChanged",
        default,
        skip_serializing_if = "Option::is_none"
    )]
    #[ts(optional)]
    pub list_changed: Option<bool>,
}

/// Present if the server offers any resources to read.
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema, TS)]
pub struct ServerCapabilitiesResources {
    #[serde(
        rename = "listChanged",
        default,
        skip_serializing_if = "Option::is_none"
    )]
    #[ts(optional)]
    pub list_changed: Option<bool>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    #[ts(optional)]
    pub subscribe: Option<bool>,
}

/// Present if the server offers any prompt templates.
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema, TS)]
pub struct ServerCapabilitiesPrompts {
    #[serde(
        rename = "listChanged",
        default,
        skip_serializing_if = "Option::is_none"
    )]
    #[ts(optional)]
    pub list_changed: Option<bool>,
}

#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema, TS)]
#[serde(tag = "method", content = "params")]
pub enum ServerNotification {
    #[serde(rename = "notifications/cancelled")]
    CancelledNotification(<CancelledNotification as ModelContextProtocolNotification>::Params),
    #[serde(rename = "notifications/progress")]
    ProgressNotification(<ProgressNotification as ModelContextProtocolNotification>::Params),
    #[serde(rename = "notifications/resources/list_changed")]
    ResourceListChangedNotification(
        <ResourceListChangedNotification as ModelContextProtocolNotification>::Params,
    ),
    #[serde(rename = "notifications/resources/updated")]
    ResourceUpdatedNotification(
        <ResourceUpdatedNotification as ModelContextProtocolNotification>::Params,
    ),
    #[serde(rename = "notifications/prompts/list_changed")]
    PromptListChangedNotification(
        <PromptListChangedNotification as ModelContextProtocolNotification>::Params,
    ),
    #[serde(rename = "notifications/tools/list_changed")]
    ToolListChangedNotification(
        <ToolListChangedNotification as ModelContextProtocolNotification>::Params,
    ),
    #[serde(rename = "notifications/message")]
    LoggingMessageNotification(
        <LoggingMessageNotification as ModelContextProtocolNotification>::Params,
    ),
}

#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema, TS)]
#[serde(untagged)]
pub enum ServerRequest {
    PingRequest(PingRequest),
    CreateMessageRequest(CreateMessageRequest),
    ListRootsRequest(ListRootsRequest),
    ElicitRequest(ElicitRequest),
}

#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema, TS)]
#[serde(untagged)]
#[allow(clippy::large_enum_variant)]
pub enum ServerResult {
    Result(Result),
    InitializeResult(InitializeResult),
    ListResourcesResult(ListResourcesResult),
    ListResourceTemplatesResult(ListResourceTemplatesResult),
    ReadResourceResult(ReadResourceResult),
    ListPromptsResult(ListPromptsResult),
    GetPromptResult(GetPromptResult),
    ListToolsResult(ListToolsResult),
    CallToolResult(CallToolResult),
    CompleteResult(CompleteResult),
}

#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema, TS)]
pub enum SetLevelRequest {}

impl ModelContextProtocolRequest for SetLevelRequest {
    const METHOD: &'static str = "logging/setLevel";
    type Params = SetLevelRequestParams;
    type Result = Result;
}

#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema, TS)]
pub struct SetLevelRequestParams {
    pub level: LoggingLevel,
}

#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema, TS)]
pub struct StringSchema {
    #[serde(default, skip_serializing_if = "Option::is_none")]
    #[ts(optional)]
    pub description: Option<String>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    #[ts(optional)]
    pub format: Option<String>,
    #[serde(rename = "maxLength", default, skip_serializing_if = "Option::is_none")]
    #[ts(optional)]
    pub max_length: Option<i64>,
    #[serde(rename = "minLength", default, skip_serializing_if = "Option::is_none")]
    #[ts(optional)]
    pub min_length: Option<i64>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    #[ts(optional)]
    pub title: Option<String>,
    pub r#type: String, // &'static str = "string"
}

#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema, TS)]
pub enum SubscribeRequest {}

impl ModelContextProtocolRequest for SubscribeRequest {
    const METHOD: &'static str = "resources/subscribe";
    type Params = SubscribeRequestParams;
    type Result = Result;
}

#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema, TS)]
pub struct SubscribeRequestParams {
    pub uri: String,
}

/// Text provided to or from an LLM.
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema, TS)]
pub struct TextContent {
    #[serde(default, skip_serializing_if = "Option::is_none")]
    #[ts(optional)]
    pub annotations: Option<Annotations>,
    pub text: String,
    pub r#type: String, // &'static str = "text"
}

#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema, TS)]
pub struct TextResourceContents {
    #[serde(rename = "mimeType", default, skip_serializing_if = "Option::is_none")]
    #[ts(optional)]
    pub mime_type: Option<String>,
    pub text: String,
    pub uri: String,
}

/// Definition for a tool the client can call.
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema, TS)]
pub struct Tool {
    #[serde(default, skip_serializing_if = "Option::is_none")]
    #[ts(optional)]
    pub annotations: Option<ToolAnnotations>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    #[ts(optional)]
    pub description: Option<String>,
    #[serde(rename = "inputSchema")]
    pub input_schema: ToolInputSchema,
    pub name: String,
    #[serde(
        rename = "outputSchema",
        default,
        skip_serializing_if = "Option::is_none"
    )]
    #[ts(optional)]
    pub output_schema: Option<ToolOutputSchema>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    #[ts(optional)]
    pub title: Option<String>,
}

fn tool_output_schema_type_default_str() -> String {
    "object".to_string()
}

/// An optional JSON Schema object defining the structure of the tool's output returned in
/// the structuredContent field of a CallToolResult.
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema, TS)]
pub struct ToolOutputSchema {
    #[serde(default, skip_serializing_if = "Option::is_none")]
    #[ts(optional)]
    pub properties: Option<serde_json::Value>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    #[ts(optional)]
    pub required: Option<Vec<String>>,
    #[serde(default = "tool_output_schema_type_default_str")]
    pub r#type: String, // &'static str = "object"
}

fn tool_input_schema_type_default_str() -> String {
    "object".to_string()
}

/// A JSON Schema object defining the expected parameters for the tool.
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema, TS)]
pub struct ToolInputSchema {
    #[serde(default, skip_serializing_if = "Option::is_none")]
    #[ts(optional)]
    pub properties: Option<serde_json::Value>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    #[ts(optional)]
    pub required: Option<Vec<String>>,
    #[serde(default = "tool_input_schema_type_default_str")]
    pub r#type: String, // &'static str = "object"
}

/// Additional properties describing a Tool to clients.
///
/// NOTE: all properties in ToolAnnotations are **hints**.
/// They are not guaranteed to provide a faithful description of
/// tool behavior (including descriptive properties like `title`).
///
/// Clients should never make tool use decisions based on ToolAnnotations
/// received from untrusted servers.
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema, TS)]
pub struct ToolAnnotations {
    #[serde(
        rename = "destructiveHint",
        default,
        skip_serializing_if = "Option::is_none"
    )]
    #[ts(optional)]
    pub destructive_hint: Option<bool>,
    #[serde(
        rename = "idempotentHint",
        default,
        skip_serializing_if = "Option::is_none"
    )]
    #[ts(optional)]
    pub idempotent_hint: Option<bool>,
    #[serde(
        rename = "openWorldHint",
        default,
        skip_serializing_if = "Option::is_none"
    )]
    #[ts(optional)]
    pub open_world_hint: Option<bool>,
    #[serde(
        rename = "readOnlyHint",
        default,
        skip_serializing_if = "Option::is_none"
    )]
    #[ts(optional)]
    pub read_only_hint: Option<bool>,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    #[ts(optional)]
    pub title: Option<String>,
}

#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema, TS)]
pub enum ToolListChangedNotification {}

impl ModelContextProtocolNotification for ToolListChangedNotification {
    const METHOD: &'static str = "notifications/tools/list_changed";
    type Params = Option<serde_json::Value>;
}

#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema, TS)]
pub enum UnsubscribeRequest {}

impl ModelContextProtocolRequest for UnsubscribeRequest {
    const METHOD: &'static str = "resources/unsubscribe";
    type Params = UnsubscribeRequestParams;
    type Result = Result;
}

#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema, TS)]
pub struct UnsubscribeRequestParams {
    pub uri: String,
}

impl TryFrom<JSONRPCRequest> for ClientRequest {
    type Error = serde_json::Error;
    fn try_from(req: JSONRPCRequest) -> std::result::Result<Self, Self::Error> {
        match req.method.as_str() {
            "initialize" => {
                let params_json = req.params.unwrap_or(serde_json::Value::Null);
                let params: <InitializeRequest as ModelContextProtocolRequest>::Params =
                    serde_json::from_value(params_json)?;
                Ok(ClientRequest::InitializeRequest(params))
            }
            "ping" => {
                let params_json = req.params.unwrap_or(serde_json::Value::Null);
                let params: <PingRequest as ModelContextProtocolRequest>::Params =
                    serde_json::from_value(params_json)?;
                Ok(ClientRequest::PingRequest(params))
            }
            "resources/list" => {
                let params_json = req.params.unwrap_or(serde_json::Value::Null);
                let params: <ListResourcesRequest as ModelContextProtocolRequest>::Params =
                    serde_json::from_value(params_json)?;
                Ok(ClientRequest::ListResourcesRequest(params))
            }
            "resources/templates/list" => {
                let params_json = req.params.unwrap_or(serde_json::Value::Null);
                let params: <ListResourceTemplatesRequest as ModelContextProtocolRequest>::Params =
                    serde_json::from_value(params_json)?;
                Ok(ClientRequest::ListResourceTemplatesRequest(params))
            }
            "resources/read" => {
                let params_json = req.params.unwrap_or(serde_json::Value::Null);
                let params: <ReadResourceRequest as ModelContextProtocolRequest>::Params =
                    serde_json::from_value(params_json)?;
                Ok(ClientRequest::ReadResourceRequest(params))
            }
            "resources/subscribe" => {
                let params_json = req.params.unwrap_or(serde_json::Value::Null);
                let params: <SubscribeRequest as ModelContextProtocolRequest>::Params =
                    serde_json::from_value(params_json)?;
                Ok(ClientRequest::SubscribeRequest(params))
            }
            "resources/unsubscribe" => {
                let params_json = req.params.unwrap_or(serde_json::Value::Null);
                let params: <UnsubscribeRequest as ModelContextProtocolRequest>::Params =
                    serde_json::from_value(params_json)?;
                Ok(ClientRequest::UnsubscribeRequest(params))
            }
            "prompts/list" => {
                let params_json = req.params.unwrap_or(serde_json::Value::Null);
                let params: <ListPromptsRequest as ModelContextProtocolRequest>::Params =
                    serde_json::from_value(params_json)?;
                Ok(ClientRequest::ListPromptsRequest(params))
            }
            "prompts/get" => {
                let params_json = req.params.unwrap_or(serde_json::Value::Null);
                let params: <GetPromptRequest as ModelContextProtocolRequest>::Params =
                    serde_json::from_value(params_json)?;
                Ok(ClientRequest::GetPromptRequest(params))
            }
            "tools/list" => {
                let params_json = req.params.unwrap_or(serde_json::Value::Null);
                let params: <ListToolsRequest as ModelContextProtocolRequest>::Params =
                    serde_json::from_value(params_json)?;
                Ok(ClientRequest::ListToolsRequest(params))
            }
            "tools/call" => {
                let params_json = req.params.unwrap_or(serde_json::Value::Null);
                let params: <CallToolRequest as ModelContextProtocolRequest>::Params =
                    serde_json::from_value(params_json)?;
                Ok(ClientRequest::CallToolRequest(params))
            }
            "logging/setLevel" => {
                let params_json = req.params.unwrap_or(serde_json::Value::Null);
                let params: <SetLevelRequest as ModelContextProtocolRequest>::Params =
                    serde_json::from_value(params_json)?;
                Ok(ClientRequest::SetLevelRequest(params))
            }
            "completion/complete" => {
                let params_json = req.params.unwrap_or(serde_json::Value::Null);
                let params: <CompleteRequest as ModelContextProtocolRequest>::Params =
                    serde_json::from_value(params_json)?;
                Ok(ClientRequest::CompleteRequest(params))
            }
            _ => Err(serde_json::Error::io(std::io::Error::new(
                std::io::ErrorKind::InvalidData,
                format!("Unknown method: {}", req.method),
            ))),
        }
    }
}

impl TryFrom<JSONRPCNotification> for ServerNotification {
    type Error = serde_json::Error;
    fn try_from(n: JSONRPCNotification) -> std::result::Result<Self, Self::Error> {
        match n.method.as_str() {
            "notifications/cancelled" => {
                let params_json = n.params.unwrap_or(serde_json::Value::Null);
                let params: <CancelledNotification as ModelContextProtocolNotification>::Params =
                    serde_json::from_value(params_json)?;
                Ok(ServerNotification::CancelledNotification(params))
            }
            "notifications/progress" => {
                let params_json = n.params.unwrap_or(serde_json::Value::Null);
                let params: <ProgressNotification as ModelContextProtocolNotification>::Params =
                    serde_json::from_value(params_json)?;
                Ok(ServerNotification::ProgressNotification(params))
            }
            "notifications/resources/list_changed" => {
                let params_json = n.params.unwrap_or(serde_json::Value::Null);
                let params: <ResourceListChangedNotification as ModelContextProtocolNotification>::Params = serde_json::from_value(params_json)?;
                Ok(ServerNotification::ResourceListChangedNotification(params))
            }
            "notifications/resources/updated" => {
                let params_json = n.params.unwrap_or(serde_json::Value::Null);
                let params: <ResourceUpdatedNotification as ModelContextProtocolNotification>::Params = serde_json::from_value(params_json)?;
                Ok(ServerNotification::ResourceUpdatedNotification(params))
            }
            "notifications/prompts/list_changed" => {
                let params_json = n.params.unwrap_or(serde_json::Value::Null);
                let params: <PromptListChangedNotification as ModelContextProtocolNotification>::Params = serde_json::from_value(params_json)?;
                Ok(ServerNotification::PromptListChangedNotification(params))
            }
            "notifications/tools/list_changed" => {
                let params_json = n.params.unwrap_or(serde_json::Value::Null);
                let params: <ToolListChangedNotification as ModelContextProtocolNotification>::Params = serde_json::from_value(params_json)?;
                Ok(ServerNotification::ToolListChangedNotification(params))
            }
            "notifications/message" => {
                let params_json = n.params.unwrap_or(serde_json::Value::Null);
                let params: <LoggingMessageNotification as ModelContextProtocolNotification>::Params = serde_json::from_value(params_json)?;
                Ok(ServerNotification::LoggingMessageNotification(params))
            }
            _ => Err(serde_json::Error::io(std::io::Error::new(
                std::io::ErrorKind::InvalidData,
                format!("Unknown method: {}", n.method),
            ))),
        }
    }
}
