From b997c007a99fdbb45b460ac08ec05e498e08e660 Mon Sep 17 00:00:00 2001 From: jokemanfire Date: Wed, 25 Jun 2025 17:45:35 +0800 Subject: [PATCH] docs: add notion clear in model.rs Signed-off-by: jokemanfire --- crates/rmcp/src/model.rs | 227 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 222 insertions(+), 5 deletions(-) diff --git a/crates/rmcp/src/model.rs b/crates/rmcp/src/model.rs index 657cdb29..8a1046f1 100644 --- a/crates/rmcp/src/model.rs +++ b/crates/rmcp/src/model.rs @@ -19,7 +19,10 @@ use serde::{Deserialize, Serialize}; use serde_json::Value; pub use tool::*; +/// A JSON object type alias for convenient handling of JSON data. +/// /// You can use [`crate::object!`] or [`crate::model::object`] to create a json object quickly. +/// This is commonly used for storing arbitrary JSON data in MCP messages. pub type JsonObject = serde_json::Map; /// unwrap the JsonObject under [`serde_json::Value`] @@ -45,6 +48,10 @@ macro_rules! object { }) }; } + +/// This is commonly used for representing empty objects in MCP messages. +/// +/// without returning any specific data. #[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Copy, Eq)] #[cfg_attr(feature = "server", derive(schemars::JsonSchema))] pub struct EmptyObject {} @@ -110,6 +117,14 @@ macro_rules! const_string { const_string!(JsonRpcVersion2_0 = "2.0"); +// ============================================================================= +// CORE PROTOCOL TYPES +// ============================================================================= + +/// Represents the MCP protocol version used for communication. +/// +/// This ensures compatibility between clients and servers by specifying +/// which version of the Model Context Protocol is being used. #[derive(Debug, Clone, Eq, PartialEq, Hash, PartialOrd)] #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))] pub struct ProtocolVersion(Cow<'static, str>); @@ -157,9 +172,15 @@ impl<'de> Deserialize<'de> for ProtocolVersion { } } +/// A flexible identifier type that can be either a number or a string. +/// +/// This is commonly used for request IDs and other identifiers in JSON-RPC +/// where the specification allows both numeric and string values. #[derive(Debug, Clone, Eq, PartialEq, Hash)] pub enum NumberOrString { + /// A numeric identifier Number(u32), + /// A string identifier String(Arc), } @@ -236,17 +257,32 @@ impl schemars::JsonSchema for NumberOrString { } } +/// Type alias for request identifiers used in JSON-RPC communication. pub type RequestId = NumberOrString; +/// A token used to track the progress of long-running operations. +/// +/// Progress tokens allow clients and servers to associate progress notifications +/// with specific requests, enabling real-time updates on operation status. #[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Hash, Eq)] #[serde(transparent)] #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))] pub struct ProgressToken(pub NumberOrString); + +// ============================================================================= +// JSON-RPC MESSAGE STRUCTURES +// ============================================================================= + +/// Represents a JSON-RPC request with method, parameters, and extensions. +/// +/// This is the core structure for all MCP requests, containing: +/// - `method`: The name of the method being called +/// - `params`: The parameters for the method +/// - `extensions`: Additional context data (similar to HTTP headers) #[derive(Debug, Clone, Default)] #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))] pub struct Request { pub method: M, - // #[serde(skip_serializing_if = "Option::is_none")] pub params: P, /// extensions will carry anything possible in the context, including [`Meta`] /// @@ -383,7 +419,10 @@ pub struct JsonRpcNotification { pub notification: N, } -// Standard JSON-RPC error codes +/// Standard JSON-RPC error codes used throughout the MCP protocol. +/// +/// These codes follow the JSON-RPC 2.0 specification and provide +/// standardized error reporting across all MCP implementations. #[derive(Debug, Clone, Copy, Default, Serialize, Deserialize, PartialEq, Eq)] #[serde(transparent)] #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))] @@ -399,10 +438,13 @@ impl ErrorCode { } /// Error information for JSON-RPC error responses. +/// +/// This structure follows the JSON-RPC 2.0 specification for error reporting, +/// providing a standardized way to communicate errors between clients and servers. #[derive(Debug, Serialize, Deserialize, Clone, PartialEq)] #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))] pub struct ErrorData { - /// The error type that occurred. + /// The error type that occurred (using standard JSON-RPC error codes) pub code: ErrorCode, /// A short description of the error. The message SHOULD be limited to a concise single sentence. @@ -480,15 +522,26 @@ impl JsonRpcBatchResponseItem { } } +/// Represents any JSON-RPC message that can be sent or received. +/// +/// This enum covers all possible message types in the JSON-RPC protocol: +/// individual requests/responses, notifications, batch operations, and errors. +/// It serves as the top-level message container for MCP communication. #[derive(Debug, Serialize, Deserialize, Clone, PartialEq)] #[serde(untagged)] #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))] pub enum JsonRpcMessage { + /// A single request expecting a response Request(JsonRpcRequest), + /// A response to a previous request Response(JsonRpcResponse), + /// A one-way notification (no response expected) Notification(JsonRpcNotification), + /// Multiple requests sent together BatchRequest(Vec>), + /// Multiple responses sent together BatchResponse(Vec>), + /// An error response Error(JsonRpcError), } @@ -558,6 +611,10 @@ impl JsonRpcMessage { } } +// ============================================================================= +// INITIALIZATION AND CONNECTION SETUP +// ============================================================================= + /// # Empty result /// A response that indicates success but carries no data. pub type EmptyResult = EmptyObject; @@ -601,22 +658,38 @@ pub type InitializeRequest = Request; + +/// Parameters sent by a client when initializing a connection to an MCP server. +/// +/// This contains the client's protocol version, capabilities, and implementation +/// information, allowing the server to understand what the client supports. #[derive(Debug, Serialize, Deserialize, Clone, PartialEq)] #[serde(rename_all = "camelCase")] #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))] pub struct InitializeRequestParam { + /// The MCP protocol version this client supports pub protocol_version: ProtocolVersion, + /// The capabilities this client supports (sampling, roots, etc.) pub capabilities: ClientCapabilities, + /// Information about the client implementation pub client_info: Implementation, } +/// The server's response to an initialization request. +/// +/// Contains the server's protocol version, capabilities, and implementation +/// information, along with optional instructions for the client. #[derive(Debug, Serialize, Deserialize, Clone, PartialEq)] #[serde(rename_all = "camelCase")] #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))] pub struct InitializeResult { + /// The MCP protocol version this server supports pub protocol_version: ProtocolVersion, + /// The capabilities this server provides (tools, resources, prompts, etc.) pub capabilities: ServerCapabilities, + /// Information about the server implementation pub server_info: Implementation, + /// Optional human-readable instructions about using this server #[serde(skip_serializing_if = "Option::is_none")] pub instructions: Option, } @@ -674,6 +747,10 @@ pub struct PaginatedRequestParam { #[serde(skip_serializing_if = "Option::is_none")] pub cursor: Option, } +// ============================================================================= +// PROGRESS AND PAGINATION +// ============================================================================= + const_string!(PingRequestMethod = "ping"); pub type PingRequest = RequestNoParam; @@ -723,75 +800,105 @@ macro_rules! paginated_result { }; } +// ============================================================================= +// RESOURCE MANAGEMENT +// ============================================================================= + const_string!(ListResourcesRequestMethod = "resources/list"); +/// Request to list all available resources from a server pub type ListResourcesRequest = RequestOptionalParam; + paginated_result!(ListResourcesResult { resources: Vec }); const_string!(ListResourceTemplatesRequestMethod = "resources/templates/list"); +/// Request to list all available resource templates from a server pub type ListResourceTemplatesRequest = RequestOptionalParam; + paginated_result!(ListResourceTemplatesResult { resource_templates: Vec }); const_string!(ReadResourceRequestMethod = "resources/read"); +/// Parameters for reading a specific resource #[derive(Debug, Serialize, Deserialize, Clone, PartialEq)] #[serde(rename_all = "camelCase")] #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))] pub struct ReadResourceRequestParam { + /// The URI of the resource to read pub uri: String, } +/// Result containing the contents of a read resource #[derive(Debug, Serialize, Deserialize, Clone, PartialEq)] #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))] pub struct ReadResourceResult { + /// The actual content of the resource pub contents: Vec, } +/// Request to read a specific resource pub type ReadResourceRequest = Request; const_string!(ResourceListChangedNotificationMethod = "notifications/resources/list_changed"); +/// Notification sent when the list of available resources changes pub type ResourceListChangedNotification = NotificationNoParam; const_string!(SubscribeRequestMethod = "resources/subscribe"); +/// Parameters for subscribing to resource updates #[derive(Debug, Serialize, Deserialize, Clone, PartialEq)] #[serde(rename_all = "camelCase")] #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))] pub struct SubscribeRequestParam { + /// The URI of the resource to subscribe to pub uri: String, } +/// Request to subscribe to resource updates pub type SubscribeRequest = Request; const_string!(UnsubscribeRequestMethod = "resources/unsubscribe"); +/// Parameters for unsubscribing from resource updates #[derive(Debug, Serialize, Deserialize, Clone, PartialEq)] #[serde(rename_all = "camelCase")] #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))] pub struct UnsubscribeRequestParam { + /// The URI of the resource to unsubscribe from pub uri: String, } +/// Request to unsubscribe from resource updates pub type UnsubscribeRequest = Request; const_string!(ResourceUpdatedNotificationMethod = "notifications/resources/updated"); +/// Parameters for a resource update notification #[derive(Debug, Serialize, Deserialize, Clone, PartialEq)] #[serde(rename_all = "camelCase")] #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))] pub struct ResourceUpdatedNotificationParam { + /// The URI of the resource that was updated pub uri: String, } +/// Notification sent when a subscribed resource is updated pub type ResourceUpdatedNotification = Notification; +// ============================================================================= +// PROMPT MANAGEMENT +// ============================================================================= + const_string!(ListPromptsRequestMethod = "prompts/list"); +/// Request to list all available prompts from a server pub type ListPromptsRequest = RequestOptionalParam; + paginated_result!(ListPromptsResult { prompts: Vec }); const_string!(GetPromptRequestMethod = "prompts/get"); +/// Parameters for retrieving a specific prompt #[derive(Debug, Serialize, Deserialize, Clone, PartialEq)] #[serde(rename_all = "camelCase")] #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))] @@ -800,14 +907,22 @@ pub struct GetPromptRequestParam { #[serde(skip_serializing_if = "Option::is_none")] pub arguments: Option, } +/// Request to get a specific prompt pub type GetPromptRequest = Request; const_string!(PromptListChangedNotificationMethod = "notifications/prompts/list_changed"); +/// Notification sent when the list of available prompts changes pub type PromptListChangedNotification = NotificationNoParam; const_string!(ToolListChangedNotificationMethod = "notifications/tools/list_changed"); +/// Notification sent when the list of available tools changes pub type ToolListChangedNotification = NotificationNoParam; -// 日志相关 + +// ============================================================================= +// LOGGING +// ============================================================================= + +/// Logging levels supported by the MCP protocol #[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Copy)] #[serde(rename_all = "lowercase")] //match spec #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))] @@ -823,97 +938,160 @@ pub enum LoggingLevel { } const_string!(SetLevelRequestMethod = "logging/setLevel"); +/// Parameters for setting the logging level #[derive(Debug, Serialize, Deserialize, Clone, PartialEq)] #[serde(rename_all = "camelCase")] #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))] pub struct SetLevelRequestParam { + /// The desired logging level pub level: LoggingLevel, } +/// Request to set the logging level pub type SetLevelRequest = Request; const_string!(LoggingMessageNotificationMethod = "notifications/message"); +/// Parameters for a logging message notification #[derive(Debug, Serialize, Deserialize, Clone, PartialEq)] #[serde(rename_all = "camelCase")] #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))] pub struct LoggingMessageNotificationParam { + /// The severity level of this log message pub level: LoggingLevel, + /// Optional logger name that generated this message #[serde(skip_serializing_if = "Option::is_none")] pub logger: Option, + /// The actual log data pub data: Value, } +/// Notification containing a log message pub type LoggingMessageNotification = Notification; +// ============================================================================= +// SAMPLING (LLM INTERACTION) +// ============================================================================= + const_string!(CreateMessageRequestMethod = "sampling/createMessage"); pub type CreateMessageRequest = Request; +/// Represents the role of a participant in a conversation or message exchange. +/// +/// Used in sampling and chat contexts to distinguish between different +/// types of message senders in the conversation flow. #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))] pub enum Role { + /// A human user or client making a request User, + /// An AI assistant or server providing a response Assistant, } +/// A message in a sampling conversation, containing a role and content. +/// +/// This represents a single message in a conversation flow, used primarily +/// in LLM sampling requests where the conversation history is important +/// for generating appropriate responses. #[derive(Debug, Serialize, Deserialize, Clone, PartialEq)] #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))] pub struct SamplingMessage { + /// The role of the message sender (User or Assistant) pub role: Role, + /// The actual content of the message (text, image, etc.) pub content: Content, } +/// Specifies how much context should be included in sampling requests. +/// +/// This allows clients to control what additional context information +/// should be provided to the LLM when processing sampling requests. #[derive(Debug, Serialize, Deserialize, Clone, PartialEq)] #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))] pub enum ContextInclusion { + /// Include context from all connected MCP servers #[serde(rename = "allServers")] AllServers, + /// Include no additional context #[serde(rename = "none")] None, + /// Include context only from the requesting server #[serde(rename = "thisServer")] ThisServer, } +/// Parameters for creating a message through LLM sampling. +/// +/// This structure contains all the necessary information for a client to +/// generate an LLM response, including conversation history, model preferences, +/// and generation parameters. #[derive(Debug, Serialize, Deserialize, Clone, PartialEq)] #[serde(rename_all = "camelCase")] #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))] pub struct CreateMessageRequestParam { + /// The conversation history and current messages pub messages: Vec, + /// Preferences for model selection and behavior #[serde(skip_serializing_if = "Option::is_none")] pub model_preferences: Option, + /// System prompt to guide the model's behavior #[serde(skip_serializing_if = "Option::is_none")] pub system_prompt: Option, + /// How much context to include from MCP servers #[serde(skip_serializing_if = "Option::is_none")] pub include_context: Option, + /// Temperature for controlling randomness (0.0 to 1.0) #[serde(skip_serializing_if = "Option::is_none")] pub temperature: Option, + /// Maximum number of tokens to generate pub max_tokens: u32, + /// Sequences that should stop generation #[serde(skip_serializing_if = "Option::is_none")] pub stop_sequences: Option>, + /// Additional metadata for the request #[serde(skip_serializing_if = "Option::is_none")] pub metadata: Option, } +/// Preferences for model selection and behavior in sampling requests. +/// +/// This allows servers to express their preferences for which model to use +/// and how to balance different priorities when the client has multiple +/// model options available. #[derive(Debug, Serialize, Deserialize, Clone, PartialEq)] #[serde(rename_all = "camelCase")] #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))] pub struct ModelPreferences { + /// Specific model names or families to prefer (e.g., "claude", "gpt") #[serde(skip_serializing_if = "Option::is_none")] pub hints: Option>, + /// Priority for cost optimization (0.0 to 1.0, higher = prefer cheaper models) #[serde(skip_serializing_if = "Option::is_none")] pub cost_priority: Option, + /// Priority for speed/latency (0.0 to 1.0, higher = prefer faster models) #[serde(skip_serializing_if = "Option::is_none")] pub speed_priority: Option, + /// Priority for intelligence/capability (0.0 to 1.0, higher = prefer more capable models) #[serde(skip_serializing_if = "Option::is_none")] pub intelligence_priority: Option, } +/// A hint suggesting a preferred model name or family. +/// +/// Model hints are advisory suggestions that help clients choose appropriate +/// models. They can be specific model names or general families like "claude" or "gpt". #[derive(Debug, Serialize, Deserialize, Clone, PartialEq)] #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))] pub struct ModelHint { + /// The suggested model name or family identifier #[serde(skip_serializing_if = "Option::is_none")] pub name: Option, } +// ============================================================================= +// COMPLETION AND AUTOCOMPLETE +// ============================================================================= + #[derive(Debug, Serialize, Deserialize, Clone, PartialEq)] #[serde(rename_all = "camelCase")] #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))] @@ -973,7 +1151,10 @@ pub struct ArgumentInfo { pub value: String, } -// 根目录相关 +// ============================================================================= +// ROOTS AND WORKSPACE MANAGEMENT +// ============================================================================= + #[derive(Debug, Serialize, Deserialize, Clone, PartialEq)] #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))] pub struct Root { @@ -995,22 +1176,34 @@ pub struct ListRootsResult { const_string!(RootsListChangedNotificationMethod = "notifications/roots/list_changed"); pub type RootsListChangedNotification = NotificationNoParam; +// ============================================================================= +// TOOL EXECUTION RESULTS +// ============================================================================= + +/// The result of a tool call operation. +/// +/// Contains the content returned by the tool execution and an optional +/// flag indicating whether the operation resulted in an error. #[derive(Debug, Serialize, Deserialize, Clone, PartialEq)] #[serde(rename_all = "camelCase")] #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))] pub struct CallToolResult { + /// The content returned by the tool (text, images, etc.) pub content: Vec, + /// Whether this result represents an error condition #[serde(skip_serializing_if = "Option::is_none")] pub is_error: Option, } impl CallToolResult { + /// Create a successful tool result pub fn success(content: Vec) -> Self { CallToolResult { content, is_error: Some(false), } } + /// Create an error tool result pub fn error(content: Vec) -> Self { CallToolResult { content, @@ -1020,7 +1213,9 @@ impl CallToolResult { } const_string!(ListToolsRequestMethod = "tools/list"); +/// Request to list all available tools from a server pub type ListToolsRequest = RequestOptionalParam; + paginated_result!( ListToolsResult { tools: Vec @@ -1028,24 +1223,38 @@ paginated_result!( ); const_string!(CallToolRequestMethod = "tools/call"); +/// Parameters for calling a tool provided by an MCP server. +/// +/// Contains the tool name and optional arguments needed to execute +/// the tool operation. #[derive(Debug, Serialize, Deserialize, Clone, PartialEq)] #[serde(rename_all = "camelCase")] #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))] pub struct CallToolRequestParam { + /// The name of the tool to call pub name: Cow<'static, str>, + /// Arguments to pass to the tool (must match the tool's input schema) #[serde(skip_serializing_if = "Option::is_none")] pub arguments: Option, } +/// Request to call a specific tool pub type CallToolRequest = Request; +/// The result of a sampling/createMessage request containing the generated response. +/// +/// This structure contains the generated message along with metadata about +/// how the generation was performed and why it stopped. #[derive(Debug, Serialize, Deserialize, Clone, PartialEq)] #[serde(rename_all = "camelCase")] #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))] pub struct CreateMessageResult { + /// The identifier of the model that generated the response pub model: String, + /// The reason why generation stopped (e.g., "endTurn", "maxTokens") #[serde(skip_serializing_if = "Option::is_none")] pub stop_reason: Option, + /// The generated message with role and content #[serde(flatten)] pub message: SamplingMessage, } @@ -1065,6 +1274,10 @@ pub struct GetPromptResult { pub messages: Vec, } +// ============================================================================= +// MESSAGE TYPE UNIONS +// ============================================================================= + macro_rules! ts_union { ( export type $U: ident = @@ -1190,6 +1403,10 @@ impl From for ClientNotification { } } +// ============================================================================= +// TESTS +// ============================================================================= + #[cfg(test)] mod tests { use serde_json::json;